我该如何避免此 .htaccess 文件中的错误?

我该如何避免此 .htaccess 文件中的错误?

我有一个博客。该博客存储/blog/在我网站的前缀下。它具有博客的常用 URL,因此文章的 URL 格式为/blog/:year/:month/:day/:title/

首先,我希望自动将访问者重定向到www子域名(以防他们忘记这样做),并且内部将根 URL 重写为/blog/,以便博客首页出现在网站首页上。我已使用文件中的以下一组重写规则实现了此目的.htaccess

RewriteEngine On

# Rewrite monkey-robot.com to www.monkey-robot.com
RewriteCond %{HTTP_HOST} ^monkey-robot\.com$
RewriteRule ^(.*)$ http://www.monkey-robot.com/$1 [R=301,L]

RewriteRule ^$             /blog/               [L]
RewriteRule ^feeds/blog/?$ /feeds/blog/atom.xml [L]

效果很好。问题是博客首页现在出现在两个不同的 URL 上://blog/。所以我想重定向URL/blog/到根 URL。最初,我尝试使用以下一组重写规则来实现此目的:

RewriteEngine On

# Rewrite monkey-robot.com to www.monkey-robot.com
RewriteCond %{HTTP_HOST} ^monkey-robot\.com$
RewriteRule ^(.*)$ http://www.monkey-robot.com/$1 [R=301,L]

RewriteRule ^$             /blog/               [L]
RewriteRule ^blog/?$       /                    [R,L]
RewriteRule ^feeds/blog/?$ /feeds/blog/atom.xml [L]

但这给了我一个无限的重定向(可能是因为前面的规则?)。所以我尝试了这个设置:

RewriteEngine On

# Rewrite monkey-robot.com to www.monkey-robot.com
RewriteCond %{HTTP_HOST} ^monkey-robot\.com$
RewriteRule ^(.*)$ http://www.monkey-robot.com/$1 [R=301,L]

RewriteRule ^$             /blog/                       [L]
RewriteRule ^blog/?$       http://www.monkey-robot.com/ [R,L]
RewriteRule ^feeds/blog/?$ /feeds/blog/atom.xml         [L]

但是我收到了 500 内部服务器错误,并显示以下日志消息:

无效命令‘[R,L]’,可能是拼写错误或由服务器配置中未包含的模块定义

发生了什么事?我不认为[R,L]这是一个语法错误。

答案1

我怀疑,通过将重写指令放在主虚拟主机配置中(而不是文件中),您可能能够避免第二个规则集中的无限循环.htaccess。无论如何,这通常是一种很好的做法,因为将重写放在虚拟主机中时,重写的运行速度会快得多,如果您可以告诉 Apache 完全忽略文件,则可以获得进一步的速度优势.htaccess

这背后的逻辑在mod_rewrite 技术文档要点如下:如您所知,重写规则可以更改给定请求对应的文件名,甚至可以更改结果文件所在的目录。事实上,您的

RewriteRule ^$ /blog/

是一个完美的例子,它将文档根目录更改为blog目录。但 Apache 需要知道目录才能确定.htaccess要检查哪些文件以进行请求。也许您可以在这里看到问题:当 Apache 到达您的.htaccess文件时,它已经已经确定了它应该访问的文件的名称,这意味着应用重写规则已经太晚了。

Apache 内部通过创建一个新的子请求(从头开始处理)并将文件中的规则注入.htaccess处理流,以便它们应用于请求来解决这个问题。这样做的副作用是,全部应用适用的重写规则再次,这意味着[L]当您在文件中使用该标志时,它就是一种谎言.htaccess。因此,即使您[L]尝试强制将规则作为最后应用的规则,但实际上并非如此;当 Apache 处理其内部子请求时,所有规则都会再次应用。

如果您无权访问主服务器配置,您可以执行以下操作:

RewriteRule ^/blog/?$    /           [R,L,NS]

NS标志可防止该规则应用于子请求。

答案2

读完评论后,我认为最直接的解决方案是将根页面重写为实际文件index.html, 我想?)。

RewriteRule ^blog/$ / [R,L]
RewriteRule ^$ /blog/index.html [L]

这样就可以避免循环。不过还有一个问题/blog/index.html——外部可访问。如果那不是一个选择,我认为你最好的选择是遵循大卫的建议并将配置提升一级。

一些备择方案我想到的是:

  • 保持/blog/index.html可访问状态并使用链接规范(不是最好的,但很容易)
  • 如果服务器脚本(PHP可能)是可访问的,在脚本级别重定向/blog/index.php/

相关内容