【问题标题】:apache redirect from non www to wwwapache从非www重定向到www
【发布时间】:2010-11-09 04:15:57
【问题描述】:

我的网站似乎没有从非 www 重定向到 www。

我的Apache配置如下:

RewriteEngine On
### re-direct to www
RewriteCond %{http_host} !^www.example.com [nc]
RewriteRule ^(.*)$ http://www.example.com/$1 [r=301,nc] 

我错过了什么?

【问题讨论】:

标签: apache redirect mod-rewrite


【解决方案1】:

使用重写引擎是解决此问题的一种非常重量级的方法。这是一个更简单的解决方案:

<VirtualHost *:80>
    ServerName example.com
    Redirect permanent / http://www.example.com/
</VirtualHost>

<VirtualHost *:80>
    ServerName www.example.com
    # real server configuration
</VirtualHost>

然后您将拥有另一个带有ServerName www.example.com&lt;VirtualHost&gt; 部分,用于您的真实服务器配置。当使用Redirect directive 时,Apache 会自动保留/ 之后的任何内容,这是一个常见的误解,即为什么这种方法不起作用(实际上它起作用)。

【讨论】:

  • 对于一个也有 ssl 虚拟主机的网站,你如何做到这一点?
  • 我在使用此建议时收到错误消息“example.com 上的网页导致重定向过多”。其他人有这个问题吗?
  • @BlackDivine:反之亦然。只需将 www.exampleexample 交换到示例中的任何位置即可。
  • @JonathanBerger 如果您的重定向太多,那么您可能没有正确配置文件。确保有 2 个虚拟主机:一个是上面的非 www,另一个是具有真实配置的 ServerName www.example.com。还要确保在 www.example.com 配置中也没有重定向(mod_alias 和 mod_rewrite)。
  • 对于一个虚拟主机服务器,比如 example.com,我有 Redirect 301 / http://example2.com/extra/,但是当它重定向时,它错过了尾部斜杠,这意味着 example.com/blah 转到 example2.com/extrablah。有任何想法吗? (Apache 2.2.22)
【解决方案2】:

http://example.com/subdir/?lold=13666 => http://www.example.com/subdir/?lold=13666

RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

【讨论】:

  • 非常简短的回答...但重点...不确定这是赞成票还是反对票
  • 哦,太好了,这可以包含在顶层的服务器配置中(如果是的话)将适用于每个虚拟主机!
  • 你好@burzumko,你是如何做到这一点的,这对于所有没有www的人都是如此,但是让example.com/subdi1/ws/* 在没有www的情况下通过?
  • 我也将此解决方案用于 HTTPS 虚拟主机。只需在第三行的 http 中添加 s
【解决方案3】:
<VirtualHost *:80>
    ServerAlias example.com
    RedirectMatch permanent ^/(.*) http://www.example.com/$1
</VirtualHost>

【讨论】:

  • 这对我不起作用;它导致到同一站点的无限重定向循环
  • @dmiller309:你是否在ServerAlias 中加入了www.
  • 你说得对,我不小心放了www。在 ServerAlias 中使用 *.通配符。因为我弄乱了 VirtualHost 条目的顺序,所以 *.通配符有机会在我认为不会匹配时匹配。
  • 这是最好的答案,因为它很干净,保持路径(与答案 #1 不同)并且不使用 Rewrite。
【解决方案4】:

要从您的 URL 网站中删除 www,请在您的 .htaccess 文件中使用此代码:

RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^(.*)$ http://%1$1 [R=301,L]

要在您的网站URL 中强制使用www,请在.htaccess 上使用此代码

RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} ^YourSite.com$
RewriteRule ^(.*)$ http://www.yourSite.com/$1 [R=301]
RewriteCond %{REQUEST_fileNAME} !-d
RewriteCond %{REQUEST_fileNAME} !-f
RewriteRule ^(([^/]+/)*[^./]+)$ /$1.html [R=301,L]

其中YourSite.com 必须替换为您的URL

【讨论】:

  • 最佳答案在这里,因为它适用于具有多个域名的网站
  • .html 的第二部分是什么??
  • 移除 $1 前的斜杠,使重定向后没有双斜杠 (//) => RewriteRule ^(.*)$ yourSite.com$1 [R=301]
【解决方案5】:
    <VirtualHost *:80>
       DocumentRoot "what/ever/root/to/source"
       ServerName www.example.com

       <Directory "what/ever/root/to/source">
         Options FollowSymLinks MultiViews Includes ExecCGI
         AllowOverride All
         Order allow,deny
         allow from all
         <What Ever Rules You Need.>
      </Directory>

    </VirtualHost>

    <VirtualHost *:80>
      ServerName example.com
      ServerAlias *.example.com
      Redirect permanent / http://www.example.com/
    </VirtualHost>

上面的代码就是这样。第一个虚拟主机块检查请求是否为 www.example.com 并在该目录中运行您的网站。

如果失败,则进入第二个虚拟主机部分。这里除了 www.example.com 之外的任何东西都被重定向到 www.example.com。

这里的顺序很重要。如果先添加第二个 virtualhost 指令,会导致重定向循环。

此解决方案会将任何请求重定向到您的域,即 www.yourdomain.com。

干杯!

【讨论】:

    【解决方案6】:

    这与许多其他建议相似,但有一些改进:

    • 无需对域进行硬编码(适用于接受多个域或环境之间的虚拟主机)
    • 保留方案 (http/https) 并忽略以前的 %{REQUEST_URI} 规则的影响。
    • 不受之前RewriteRules 影响的路径部分如%{REQUEST_URI} 是。

      RewriteCond %{HTTP_HOST} !^www\. [NC]
      RewriteRule ^(.*)$ %{REQUEST_SCHEME}://www.%{HTTP_HOST}/$1 [R=301,L]
      

    【讨论】:

    • 几乎完美。它必须是 %{HTTP_HOST}$1,而不是 %{HTTP_HOST}/$1(否则斜杠会加倍)
    • @Michael Wyraz:这里的斜线不加倍吗?!
    【解决方案7】:

    非 www => www 和相反 www => 非 www 的重定向代码。 .htaccess 文件中没有硬编码域和方案。所以源域和http/https版本会被保留。

    APACHE 2.4 及更新版本

    非万维网 => 万维网:

    RewriteEngine On
    RewriteCond %{HTTP_HOST} !^www\. [NC]
    RewriteRule ^ %{REQUEST_SCHEME}://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
    

    WWW => 非WWW:

    RewriteEngine On
    RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
    RewriteRule ^ %{REQUEST_SCHEME}://%1%{REQUEST_URI} [R=301,L]
    

    注意:不能在 %{REQUEST_SCHEME} 不可用的 Apache 2.2 上工作。为了与 Apache 2.2 兼容,请使用以下代码或将 %{REQUEST_SCHEME} 替换为固定的 http/https。


    APACHE 2.2 及更新版本

    非万维网 => 万维网:

    RewriteEngine On
    
    RewriteCond %{HTTPS} off
    RewriteCond %{HTTP_HOST} !^www\. [NC]
    RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
    
    RewriteCond %{HTTPS} on
    RewriteCond %{HTTP_HOST} !^www\. [NC]
    RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
    

    ...或更短的版本...

    RewriteEngine On
    RewriteCond %{HTTP_HOST} !^www\. [NC]
    RewriteCond %{HTTPS}s ^on(s)|offs
    RewriteRule ^ http%1://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
    

    WWW => 非WWW:

    RewriteEngine On
    
    RewriteCond %{HTTPS} off
    RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
    RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L]
    
    RewriteCond %{HTTPS} on
    RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
    RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L]
    

    ... 不能使用更短的版本,因为 %N 仅在最后一个 RewriteCond 中可用...

    【讨论】:

    • Apache 2.4 配置解决了这个问题,感谢您的干净回答..!!
    【解决方案8】:
    RewriteCond %{HTTP_HOST} ^!example.com$ [NC]
    RewriteRule ^(.*)$ http://www.example.com/$1 [R=301,L]
    

    这从 HTTP_HOST 变量开始,它只包含传入 URL (example.com) 的域名部分。假设域名不包含www. 并且与您的域名完全匹配,那么 RewriteRule 就会发挥作用。模式^(.*)$ 将匹配REQUEST_URI 中的所有内容,这是HTTP 请求(foo/blah/index.html) 中请求的资源。它将其存储在反向引用中,然后用于用新域名(以 www 开头的域名)重写 URL。

    [NC] 表示不区分大小写的模式匹配,[R=301] 表示使用代码 301 的外部重定向(资源永久移动),[L] 停止所有进一步的重写,并立即重定向。

    【讨论】:

      【解决方案9】:

      如果您使用的是 Apache 2.4,则无需启用 rewrite apache 模块,您可以使用以下内容:

      # non-www to www
      <If "%{HTTP_HOST} = 'domain.com'">
        Redirect 301 "/" "http://www.domain.com/"
      </If>
      

      【讨论】:

      • 被低估的答案。使用它,可以避免额外的虚拟主机,这对于自动化 Let'sEncrypt 脚本很有好处。
      • 另外,如果您使用的是 ANSIBLE,从 ANSIBLE 2.0 开始,您现在可以在一个任务中轻松地将块插入文件中,更多详细信息请点击此处docs.ansible.com/ansible/2.5/modules/blockinfile_module.html
      【解决方案10】:

      我跑了这个...

       RewriteEngine on
       RewriteCond %{HTTP_HOST} !^www.*$ [NC]
       RewriteRule ^/.+www\/(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]
      

      我需要它对我们新服务器上的 25+ 个域是通用的,所以这个指令在我的 virtual.conf 文件中的 标记中。 (dir 是所有 docroot 的父级)

      尽管http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html 说它只是在主机和端口之后的东西,但我不得不对重写规则进行一些修改,因为完整的 docroot 正在模式匹配中进行。

      【讨论】:

        【解决方案11】:

        将 domain.tld 重定向到 www。

        可以在 Apache 指令或 .htaccess 文件中添加以下行:

        RewriteEngine on    
        RewriteCond %{HTTP_HOST} .
        RewriteCond %{HTTP_HOST} !^www\. [NC]
        RewriteRule ^ http%{ENV:protossl}://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
        
        • 其他 sudomains 仍在工作。
        • 无需调整线条。只需将它们复制/粘贴到正确的位置即可。

        如果您修改虚拟主机,请不要忘记应用 apache 更改。

        (基于默认的 Drupal7 .htaccess 但在许多情况下应该可以工作)

        【讨论】:

          【解决方案12】:

          这很简单!

          RewriteEngine On
          RewriteCond %{HTTP_HOST} !^www\. [NC]
          RewriteRule ^(.*)$ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
          

          【讨论】:

            【解决方案13】:
            <VirtualHost *:80>
                ServerAlias example.com
                RedirectMatch permanent ^/(.*) http://www.example.com/$1
            </VirtualHost>
            

            这不仅会重定向域名,还会重定向内部 pages.like...

            example.com/abcd.html               ==>    www.example.com/abcd.html
            example.com/ab/cd.html?ef=gh   ==>强>    www.example.com/ab/cd.html?ef=gh

            【讨论】:

            • 谢谢。很有帮助。
            【解决方案14】:

            试试这个:

            RewriteEngine on
            RewriteCond %{HTTP_HOST} ^example.com$ [NC]
            RewriteRule ^(.*) http://www.example.com$1 [R=301]
            

            【讨论】:

              【解决方案15】:

              不要总是使用Redirect permanent(或者为什么它可能会在未来引起问题)

              如果以后有机会添加子域,请不要使用redirect permanent

              因为如果客户使用了未注册为 VirtualHost 的子域,即使稍后注册,他也可能永远无法访问此子域。

              redirect permanent 向客户端(浏览器)发送一个HTTP 301 Moved Permanently,其中很多会永久缓存此响应(直到[手动]清除缓存)。因此,使用该子域将始终自动重定向到 www.*** 而无需再次请求服务器。

              How long do browsers cache HTTP 301s?

              所以只需使用Redirect

              <VirtualHost *:80>
                ServerName example.com
              
                Redirect / http://www.example.com/
              </VirtualHost>
              

              Apache.org - When not to use mod_rewrite

              Apache.org - Canonical Hostnames

              【讨论】:

                【解决方案16】:

                RewriteEngine On RewriteCond %{HTTP_HOST} ^yourdomain.com [NC] RewriteRule ^(.*)$ http://www.yourdomain.com/$1 [L,R=301]

                检查这个完美的工作

                【讨论】:

                  【解决方案17】:

                  -如果您托管多个域名(可选)

                  -如果所有这些域名都使用 https(应该如此)

                  -如果您希望所有这些域名都使用 www dot domainName

                  这将避免双重重定向(http://non www 到 http://www 然后到 https://www)

                  <VirtualHost *:80>
                  RewriteEngine On
                  RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$ [NC]
                  RewriteRule ^(.*)$ https://www.%1$1 [R=301,L]
                  </VirtualHost>
                  

                  <VirtualHost *:443>
                  RewriteEngine On
                  RewriteCond %{HTTP_HOST} !^www\. [NC]
                  RewriteRule ^(.*)$ https://www.%{HTTP_HOST}$1 [R=301,L]
                  </VirtualHost>
                  

                  你应该把重定向代码301改成最方便的一个

                  【讨论】:

                    【解决方案18】:

                    到 301 将所有直接向域发出的请求重定向到您可以使用的 www:

                    RewriteEngine On
                    
                    RewriteCond %{HTTP_HOST} !^([^.]+\.[^.]+){2,}$ [NC]
                    RewriteRule ^(.*)$ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
                    

                    这样做的好处是,如果您有任何有效的子域,这将起作用,例如

                    example.com 已重定向到 www.example.com

                    foo.example.com 没有重定向

                    bar.example.com 没有重定向

                    【讨论】:

                      【解决方案19】:

                      我也遇到了同样的问题。 但解决了这个

                      RewriteEngine On RewriteCond %{HTTP_HOST} !^www\. RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]

                      此规则将非 www 重定向到 www。

                      这个规则将www重定向到非www

                      RewriteEngine On RewriteCond %{HTTP_HOST} !^my-domain\.com$ [NC] RewriteRule ^(.*)$ http://my-domain.com/$1 [R=301,L]

                      参考http://dense13.com/blog/2008/02/27/redirecting-non-www-to-www-with-htaccess/

                      【讨论】:

                        【解决方案20】:

                        这对我有用:

                        RewriteCond %{HTTP_HOST} ^(?!www.domain.com).*$ [NC]
                        RewriteRule ^(.*)$  http://www.domain.com$1  [R=301,L]
                        

                        在将所有域重定向到 www 子域时,我使用前瞻模式 (?!www.domain.com) 排除 www 子域,以避免 Apache 中的无限重定向循环。

                        【讨论】:

                          【解决方案21】:

                          我使用的代码是:

                          RewriteEngine On
                          RewriteBase /
                          RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
                          RewriteRule ^(.*)$ http://%1/$1 [R=301,L]
                          

                          【讨论】:

                            【解决方案22】:

                            如果您只想加载 https 版本的 www,请在 apache 虚拟主机文件中使用以下配置。所有这些都可以包含在一个文件中。

                            将所有http重定向到www的https:

                            <VirtualHost *:80>
                                ServerName example.com
                                ServerAlias www.example.com
                                Redirect permanent / https://www.example.com/
                            </VirtualHost>
                            

                            将 https 非 www 重定向到 https www:

                            <VirtualHost *:443>
                                ServerName example.com
                                Redirect permanent / https://www.example.com/
                            </VirtualHost>
                            

                            真实服务器配置

                            <VirtualHost *:443>
                                ServerAdmin hostmaster@example.com
                                DocumentRoot "/path/to/your/sites/.htaccess-file-folder"
                                SetEnv APPLICATION_ENV "production"
                            
                                <Directory "/path/to/your/sites/.htaccess-file-folder">
                                        Options Indexes FollowSymLinks
                                        DirectoryIndex index.php index.html
                                        AllowOverride All
                                        Order allow,deny
                                        Allow from all
                                </Directory>
                                ServerName www.example.com
                                
                                SSLEngine ON
                                SSLCertificateFile "/path/to/your/example.cert.pem"
                                SSLCertificateKeyFile "/path/to/your/example.key.pem"
                            
                                ErrorLog /path/to/your/example.com-error.log
                                CustomLog /path/to/your/example.com-access.log combined
                                #Your other configurations if you have
                            </VirtualHost>
                            

                            【讨论】:

                              【解决方案23】:

                              这是我自己网站的配置,效果很好。

                              <IfModule mod_ssl.c>
                                <VirtualHost *:443>
                                  ServerAdmin admin@domain.com
                              
                                  ServerName www.domain.com
                                  ServerAlias domain.com
                              
                                  DocumentRoot /var/www/html/domain
                              
                                  <Directory /var/www/html/domain/>
                                    Options FollowSymLinks
                                    AllowOverride All
                                    Require all granted
                                  </Directory>
                              
                                  # Redirect non-www to www
                                  RewriteEngine On
                              
                                  RewriteCond %{HTTP_HOST} !^www\. [NC]
                                  RewriteRule ^(.*)$ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
                              
                                  ErrorLog ${APACHE_LOG_DIR}/error.log
                                  CustomLog ${APACHE_LOG_DIR}/access.log combined
                              
                                  Include /etc/letsencrypt/options-ssl-apache.conf
                                  SSLCertificateFile /etc/letsencrypt/live/domain.com/fullchain.pem
                                  SSLCertificateKeyFile /etc/letsencrypt/live/domain.com/privkey.pem
                                </VirtualHost>
                              </IfModule>
                              

                              【讨论】:

                                【解决方案24】:

                                如果使用上述两个&lt;VirtualHost *:80&gt;块的解决方案不同ServerNames...

                                <VirtualHost *:80>
                                    ServerName example.com
                                    Redirect permanent / http://www.example.com/
                                </VirtualHost>
                                <VirtualHost *:80>
                                    ServerName www.example.com
                                </VirtualHost>
                                

                                ...那么您也必须设置NameVirtualHost On

                                如果您不这样做,Apache 不允许自己使用不同的ServerNames 来区分块,因此您会收到以下错误消息:

                                [warn] _default_ VirtualHost overlap on port 80, the first has precedence
                                

                                ...要么没有重定向发生,要么你有一个无限的重定向循环,这取决于你先放哪个块。

                                【讨论】:

                                  【解决方案25】:

                                  我在 WP Multisite 上有一个类似的任务,其中重定向规则必须是通用的(对于我要添加到网络的任何给定域)。我首先解决了向域(停放域)添加通配符的问题。注意 . .com 之后。

                                  CNAME * domain.com.
                                  

                                  然后我将以下行添加到多站点根目录下的 .htaccess 文件中。我想它适用于任何网站。

                                  RewriteEngine On
                                  RewriteBase /
                                  RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
                                  RewriteRule ^(.*)$ http://%1/$1 [R=301,L]
                                  

                                  希望这会有所帮助。

                                  ps。如果您想从非 www 重定向到 www,请将最后一行更改为

                                  RewriteRule ^(.*)$ http://www.%1/$1 [R=301,L]
                                  

                                  【讨论】:

                                    【解决方案26】:

                                    我发现在使用多个虚拟主机时使用 ServerAlias 更容易(也更有用)。

                                    <VirtualHost x.x.x.x:80>
                                        ServerName www.example.com
                                        ServerAlias example.com
                                        ....
                                    </VirtualHost>
                                    

                                    这也适用于 https 虚拟主机。

                                    【讨论】:

                                    • 另一个开车通过的downvote。想解释一下,哦,伟大的 httpd 之神,谁懒得解释反对票?
                                    • 这使得您有多个域托管同一个站点。根据您的情况和底层网络服务器的运行情况,您可能会遇到 cookie 无法保留、人们感到困惑以及搜索引擎问题(这将被视为 2 个不同的站点)的问题。