重写性能,以及在 .htaccess 中有效但在 vhost 中无效的规则

重写性能,以及在 .htaccess 中有效但在 vhost 中无效的规则

我正在努力将 .htaccess 规则移至我们的 vhost_ssl.conf 文件。我遇到了一些问题,这些规则在 .htaccess 中运行良好,但在 vhost 中却无法运行。例如,在 .htaccess 中,以下规则运行良好:

RewriteRule ^example$ /example/ [L,R=301]
RewriteRule ^example/$ somewhere/something.php [QSA,L]

这个想法是,如果有人访问 example.com/example - 他们将被重定向到 example.com/example/(只需添加尾部斜杠)。然后 URL 的尾部斜杠版本将在后台重写。

当我将其移至 vhost 时:

RewriteRule ^/example/$ somewhere/something.php [QSA,L]

我遇到了一些困难:

  1. 它变成了一个无限循环的重定向(我的服务器在 10 处停止它),因为第一个规则总是被触发
  2. 在我注释掉第一条规则后,我收到“错误请求”400 错误:

错误请求 您的浏览器发送了此服务器无法理解的请求。客户端发送了格式错误的主机标头

知道为什么会发生这种情况吗?如果这意味着什么,我们正在运行 apache/nginx。我读了 SF 上关于类似问题的另一个帖子,回复是这是一个上下文问题,需要在重写的最终目标前添加一个斜杠。但就我的情况而言,当我这样做时:

RewriteRule ^/example/$ /somewhere/something.php [QSA,L]

错误变为:

Unable to execute 'example/': No such file or directory

另外,在 vhost 中的性能方面,是否存在区别,例如:

RewriteRule ^/example/$ somewhere/something.php [QSA,L]

对比

RewriteCond %{REQUEST_URI} ^/example/$
RewriteRule .* somewhere/something.php [QSA,L]

我觉得第一个版本会更好,它应该能用更少的代码实现相同的目标。但也许单独使用 RewriteCond 会让整体效率更高?

编辑:这是 vhost_ssl

RewriteEngine on
#canonocanconcical fix
RewriteCond %{HTTP_HOST} ^example\.com [NC]
RewriteRule ^(.*) https://www.example.com$1 [R=301,L]
RewriteCond %{QUERY_STRING} !Per_Page=([0-9]+)
RewriteCond %{QUERY_STRING} show=([0-9]+)
RewriteRule c-([A-Za-z0-9-_]+)\.htm c-$1.htm?Per_Page=%1 [QSA,R=301]
RewriteCond %{QUERY_STRING} !CatListingOffset=([0-9]+)
RewriteCond %{QUERY_STRING} Offset=([0-9]+)
RewriteRule c-([A-Za-z0-9-_]+)\.htm /c-$1.htm?CatListingOffset=%1 [QSA]

答案1

  1. 记得添加前斜线
  2. 阅读 Apache 文档,尤其是关于很多事情通常不需要 mod_rewrite 的部分(可以使用 mod_alias 处理):https://httpd.apache.org/docs/2.4/rewrite/avoid.html
  3. 请记住 - 即使使用标志 L,重写也可能无法完成,而是从顶部重新开始。这通常可以解释无限循环,另请参阅https://stackoverflow.com/a/6481199/2444812
  4. 如果你无法弄清楚,请创建一个最小示例(最好在本地或开发系统上,而不是在生产上)并启用 mod_rewrite 日志记录,请参阅https://stackoverflow.com/questions/286004/hidden-features-of-mod-rewrite

1. 记得添加前斜杠

在 .htaccess 中有效(但在通用配置中无效):

RewriteRule ^example$ /example/ [L,R=301]

在一般配置下工作:

RewriteRule ^/example$ /example/ [L,R=301]

区别在于前导斜杠 (/)。

我建议总是使用这样的方法:

RewriteRule ^/?example$ /example/ [L,R=301]

...两者都适用(因为它使前导斜杠成为可选项)。这样,当您现在或将来将规则从 .htaccess 移至常规配置(或反之亦然)时,就不会再遇到此问题。

参见文档:

在每个目录上下文中(即在 .htaccess 文件和目录块中),这些规则是在 URL 已转换为文件名后应用的。因此,mod_rewrite 最初将 RewriteRule 指令与之比较的 URL 路径是已翻译文件名的完整文件系统路径将当前目录路径(包括末尾的斜杠)从前面删除

特别要记住的是the leading directory path will be stripped off of the URL

(...在 .htaccess 上下文中)

https://httpd.apache.org/docs/2.4/rewrite/tech.html

答案2

?你太复杂了,你可以使用量词和单个重写规则来匹配带有和不带有尾随斜杠的相同 url :

RewriteRule ^example/?$ http://example.com/somewhere/something.php [L,R=301]

为了避免循环,请确保example!= somewhere

相关内容