给定一个 Apache 2.x Web 服务器,它使用Content Negotiation ( +MultiViews
) 来访问没有扩展名的 URL(例如,allow /foo
vs. /foo.php
or ),当有人实际上尝试使用这些扩展名时/foo.html
,如何发出301 永久重定向?
目标是让所有道路都通向 URL 的sans 扩展版本,所以/foo/
转到/foo
,然后/foo.html
转到/foo
。事实证明,后者很棘手。(用例:互联网上散落的遗留 URL 仍在使用扩展。我们希望这些 URL 被永久重定向。)
有规范的链接元素,但即使在随附的幻灯片中,建议最好首先执行重定向服务器端。
我一直在用mod_rewrite尝试这个,但看起来 Apache 就像是“打败了我”。就好像扩展被简单地忽略了一样。“不需要,我已经解决了”阿帕奇说。但是你不能处理永久重定向,因此扩展和无扩展变体都是允许的。不是想要的结果。:)
这是一个例子。给定一个由小写字母组成的 2-4 个字符的文件名,以及一个放在 中的测试文件/foo/file.html
,我们希望永久重定向到/foo/file
:
Options +MultiViews
RewriteEngine on
...
RewriteRule ^foo/([a-z]{2,4}).html/$ /foo/$1 [R=301,L]
/foo/file/
并重定向到,但当然/foo/file.html/
不会。如果我们尝试如下规则(注意 $ 之前缺少斜杠):/foo/file
/foo/file.html
RewriteRule ^foo/([a-z]{2,4}).html$ /foo/$1 [R=301,L]
...我们最终得到了太多的重定向,因为 Apache 的行为就好像规则如下,所以它最终会追逐自己的尾巴:
RewriteRule ^foo/([a-z]{2,4})$ /foo/$1 [R=301,L]
为了让自己变得太聪明,我还尝试了嵌套括号:
RewriteRule ^foo/(([a-z]{2,4}).html)$ /foo/$2 [R=301,L]
没有骰子。重定向循环城市。
真正好的是“集体”捕捉这种事情,这样我就不会在 htaccess 中漂浮所有这些特殊情况。
另一个 SO question 开始针对处理 html 文件的单一案例解决此问题,但建议的解决方案表面上需要禁用 Content Negotiation,如果您仍想将它用于图像和其他文件扩展名(因为它在我的情况)。
额外的功劳:我们还想避免尾部斜杠,所以如果有人尝试/foo/
(它本身可能是 .html 或 .php 文件),/foo
无论如何都会去。第一条规则(上面)实现了这一点,但我认为这是由于 +MultiViews。我对在DirectorySlash
这里使用表示怀疑,因为那里可能存在一些风险,使其不值得。