我有一个博客。该博客存储/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
到/