mod_negotiation 和 mod_rewrite

mod_negotiation 和 mod_rewrite

我正在尝试配置一个 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$),它应该按预期工作。

相关内容