我正在尝试配置一个 URL 方案,该方案 a) 允许省略“.html”扩展名,并且 b) 在某些条件下发送 403(禁止)错误。但是,使用以下设置:
Options +MultiViews
RewriteRule ^foo/bar$ - [F]
如果我请求,/foo/bar
我会收到 404(未找到)错误,错误日志中会显示“无法协商”行。请求/foo/bar.html
做工作,所以我猜测内容协商优先于 RewriteRule,并不断寻找替代 URL,直到找到 200。事实上,我已经通过使用文件bar.txt
和仅针对 .html 文件的 RewriteRule 进行测试,基本证实了这一点。
那么,有没有办法修改 mod_negotiation 的行为,使其在遇到 Forbidden 错误时立即“放弃”?
更新
注意:我似乎可以通过禁用 MultiViews 并使用 mod_rewrite 来解决这个问题,例如
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule !.*\.html$ %{REQUEST_FILENAME}.html [L]
但我猜这样效率会低一些,而且需要处理更多的配置
答案1
根据您省略前导斜杠的事实^foo
,我猜测这是在<Directory>
块或htaccess
文件中配置的?
这实际上是本例中问题的原因;在这种情况下,重写规则是在请求映射到文件系统(并且已.html
被附加)之后应用的。
来自文档:
在 VirtualHost 上下文中,模式最初将与 URL 中主机名和端口之后、查询字符串之前的部分进行匹配(例如“/app1/index.html”)。
在目录和 htaccess 上下文中,模式最初将与文件系统路径进行匹配,在删除引导服务器到当前 RewriteRule 的前缀之后(例如“app1/index.html”或“index.html”,具体取决于指令的定义位置)。
将您的RewriteRule
配置移至上下文<VirtualHost>
(并相应地修改您的匹配,从^foo/bar$
到^/foo/bar$
),它应该按预期工作。