为什么我的RewriteRule所在的位置会出现双斜杠?


9

我正在使用以下代码将所有www请求定向到非www URL:

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

这在我的网站根目录下的.htaccess文件中非常有效。
例如,
www.example.com-> example.com/
www.example.com/-> example.com/
www.example.com/other_page-> example.com/other_page

但是,如果我将相同的代码移到VirtualHost配置中,则重写的URL包含双斜杠。
www.example.com-> example.com//
www.example.com/-> example.com//
www.example.com/other_page-> example.com//other_page

我通过从重写规则中删除斜杠来修复它:

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

但是我不明白原因。有人知道为什么吗?

Answers:


10

据我了解,在.htaccess文件中,mod_rewrite在您的规则中处理的字符串是相对于.htaccess文件所在的目录的,因此其开头不会带有/。

在VirtualHost条目中,它处理的字符串是服务器根目录的绝对字符串,因此包含/。

它在mod_rewrite的工作方式上产生了细微的差异。

这是一个有类似问题和解决方案的人:

http://forum.modrewrite.com/viewtopic.php?p=56322&sid=77f72967f59200b5b5de174440234c3a

假设我记得自己正确地进行了转义,这在两种情况下都应该起作用:

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

谢谢!现在我至少知道了为什么。但是,由于某些原因,这是否比在我最初的问题中显示的$ 1之前删除/更好?
davekaro

1
不管是好是坏,这只是您可以在VirtualHost的.htaccess之间交换的一个块,而不必每次都对其进行编辑以处理上下文差异。如果您的方式适合您,请坚持下去!:)
Neobyte

哦,对了-您的方法可以在.htaccess和VirtualHost中使用。这使IMO变得更好:)
davekaro

4
我遇到了与@davekaro完全相同的问题,并尝试了解决方案。最后一行对我不起作用。RewriteRule ^/?(.*)$ http://example.com/$1 [R=301,L]做到了。
肯尼·拉沙特

2

发生这种情况的原因是,您正在使用捕获一个初始斜杠,(.*)然后在新位置之前应用了另一个斜杠/$1。以前没有发生过,因为在按目录上下文而不是按服务器上下文中操作时,mod_rewrite的行为略有不同。

您可以通过选择先占斜线来避免这种情况。另外,您可以在具有多余域的空VirtualHost中使用RedirectMatch,这将减少处理量,并使外观看起来更整洁。

<VirtualHost *>
ServerName example.com
ServerAlias other.example.com
..
RedirectMatch permanent ^/?(.*) http://example.com/$1
</VirtualHost>


真好 我喜欢RedirectMatch方法。我可能会这样做,因为它确实是我想要完成的重定向。
davekaro

1

为了完整起见,我将其包括在内。

Apache文档解释了为什么发生这种情况非常好,就是“RewriteBase”指令存在的原因。

只要在您的.htaccess文件中包含“ RewriteBase”指令,就可以实现所需的结果。

例:

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

从Apache 2.2 mod_rewrite文档中:

RewriteBase伪指令显式设置每个目录重写的基本URL。

我的经验法则是,几乎总是在.htaccess文件中使用“ RewriteBase”,而不是在Apache配置中使用它。


0

我没有时间处理这个问题,所以只将//重写为/ :)

RewriteCond %{THE_REQUEST} //
RewriteRule ^(.*)$ http://domain.com [R=301,L]
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.