apache从非www重定向到www


206

我的网站似乎没有从非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] 

我想念什么?


1
对于.htaccess基础解决方案,我建议针对直径问题提出一个答案:stackoverflow.com/a/5262044/367456
hakre 2014年

这很好,它的确在网址中添加了一个斜杠,因此在美元之前不要使用斜杠。
wuxmedia

Answers:


510

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

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

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

然后,您将在另一<VirtualHost>部分中ServerName www.example.com了解实际的服务器配置。/当使用Redirect指令时,Apache会自动保留所有内容,这是一个常见的误解,说明该方法为何行不通(实际上是行得通)。


20
对于具有ssl虚拟主机的网站,您该怎么做?
Shabbyrobe 2010年

28
使用此建议时,出现错误“ example.com上的网页导致太多重定向”。别人有这个问题吗?
乔纳森·伯杰

4
@BlackDivine:在另一个方向上进行操作并没有什么神奇之处。只需交换它们www.example以及example它们出现在样本中的任何位置。
Greg Hewgill

11
@JonathanBerger如果重定向太多,则可能是文件配置不正确。确保具有2个VirtualHost:一个带有非www的虚拟主机(上面是一个),另一个带有ServerName www.example.com的虚拟主机(具有实际配置)。另外,还要确保在www.example.com配置中也没有重定向(mod_alias和mod_rewrite)。
2013年

3
对于虚拟主机服务器(例如example.com),我拥有,Redirect 301 / http://example2.com/extra/但是当它重定向时,它会丢失尾部的斜杠,即example.com/blah转到example2.com/extrablah。有任何想法吗?(Apache 2.2.22)
Peter Howe

87

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]

3
很简单的答案......但是到了点...不知道如果这是一个向上或向下投票
thecoshman

2
哦,这很整洁,可以将其包含在顶级服务器配置中(如果有的话)将应用于每个虚拟主机!
thenickdude

您好@burzumko您是如何实现这一点的,这对于没有www的所有人都是正确的,但是,让我们说example.com/subdi1/ws/* 没有www的情况如何?
黑色Sensei

1
我也将此解决方案用于HTTPS虚拟主机。只需添加一个s在第三行中到http。
rodrigoap

46
<VirtualHost *:80>
    ServerAlias example.com
    RedirectMatch permanent ^/(.*) http://www.example.com/$1
</VirtualHost>

这对我没有用;它导致了到同一站点的无限重定向循环
dmiller309

1
@ dmiller309:您是否恰好包含www.在中ServerAlias
cherouvim 2014年

2
您说得对,我不小心把www。在ServerAlias中使用*。通配符。因为我弄乱了VirtualHost条目的顺序,所以*。我不认为通配符有机会比赛。
dmiller309

7
这是最佳答案,因为它很干净,可以保留路径(与答案1不同),并且不使用重写。
schieferstapel,2015年

30

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

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

要强行www进入您的网站,请URL使用以下代码.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


最佳答案在这里,因为它适用于多个域名<3的网站
Clement Herreman

2
.html的第二部分是什么?
内森·H

6
在$ 1之前删除斜杠,以便在重定向后没有双斜杠(//)=> RewriteRule ^(。*)$ yourSite.com $ 1 [R = 301]
Kevin Campion

22
    <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。

干杯!


16

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

  • 无需对域进行硬编码(与接受多个域的虚拟主机一起使用或在环境之间使用)
  • 保留方案(http / https),并忽略先前的效果 %{REQUEST_URI}规则。
  • 路径部分不受先前RewriteRules之类的影响%{REQUEST_URI}

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

4
几乎完美。它必须是%{HTTP_HOST} $ 1,而不是%{HTTP_HOST} / $ 1(否则它将使斜杠翻倍)
Michael Wyraz

@Michael Wyraz:这里的斜线不加倍吗?
not2savvy

10
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)中请求的资源。它将其存储在反向引用中,该反向引用随后用于使用新域名(以开头的域名)重写URL www

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


6

非www => www和相反www => non-www的重定向代码。.htaccess文件中没有硬编码域和方案。因此,将保留原始域和http / https版本。

APACHE 2.4及更高版本

非WWW => WWW:

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

万维网=>非万维网:

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及更高版本

非WWW => WWW:

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]

万维网=>非万维网:

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 config解决了该问题,谢谢您的答复。
KimchiMan

5

我跑了这个...

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

对于新服务器上的25个以上的域,我需要具有通用性,因此此指令位于我的virtual.conf文件的<Directory>标记中。(目录是所有文档根目录的父目录)

尽管http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html说了什么,但是我还是要对重写规则做一点修改,因为完整的docroot都是通过模式匹配传递的关于它只是主机和端口之后的东西。


5

如果您使用的是Apache 2.4,则无需启用重写apache模块,则可以使用以下代码:

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

1
被低估的答案。使用此功能,可以避免其他虚拟主机,这对于自动化的Let'sEncrypt脚本是很有用的。
保罗

另外,如果您使用的是ANSIBLE,则自ANSIBLE 2.0起,您现在可以轻松地在一个任务中将一个块插入文件中,此处有更多详细信息docs.ansible.com/ansible/2.5/modules/blockinfile_module.html
sys0dm1n

3

将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]
  • 其他sudomain仍在工作。
  • 无需调整线。只需将它们复制/粘贴到正确的位置即可。

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

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


3

这很简单!

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

2
<VirtualHost *:80>
    ServerAlias example.com
    RedirectMatch permanent ^/(.*) http://www.example.com/$1
</VirtualHost>

这样不仅可以重定向域名,还可以重定向内部页面。例如...

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


谢谢你 很有帮助。
安东尼

2

试试这个:

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

2

不要总是使用 Redirect permanent(或为什么以后可能会引起问题)

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

因为如果客户使用了未注册为的子域 VirtualHost即使以后再注册他也可能永远也不会到达该子域。

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

请参阅浏览器将HTTP 301缓存多长时间?

所以就用 Redirect

<VirtualHost *:80>
  ServerName example.com

  Redirect / http://www.example.com/
</VirtualHost>

Apache.org-何时不使用mod_rewrite

Apache.org-规范主机名


1

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

检查这项完美的工作



0

这对我有用:

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

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


0

我使用的代码是:

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

0

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

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

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

这将避免双重重定向(从http://非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更改为最方便的一种


-1

如果使用<VirtualHost *:80>具有不同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

...或者没有重定向发生,或者您有无限的重定向循环,具体取决于您首先放置的块。


-1

我在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]

-2

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

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

这也适用于https vhosts。


另一个过分的投票。小心解释,哦,httpd的强大之神,谁不介意解释低票?
安东尼

1
这样一来,您就可以拥有多个托管同一站点的域。根据您的情况和基础网络服务器的运行情况,您将遇到Cookie无法继续存在的问题,人们感到困惑以及搜索引擎问题(将其视为2个不同的站点)。
Jeffrey Van Alstine
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.