.htaccess 中的重写引擎以捕获不以 html 结尾的文件

Posted

技术标签:

【中文标题】.htaccess 中的重写引擎以捕获不以 html 结尾的文件【英文标题】:Rewriteengine in .htaccess to catch files not ending in html 【发布时间】:2010-10-10 21:07:49 【问题描述】:

我想在标准 LAMP 托管情况下使用 mod rewrite in 将 /directory 等网页地址转换为 /directory/index.html。我所拥有的适用于以斜杠结尾的地址。我找不到处理不以斜线结尾的地址的方法。

看起来应该起作用的是:

rewriterule ^(.*)/$ $1/index.html [L] /* addresses ending in / */
rewriterule ^(.*(?!html))$ $1/index.html [L] /* where the problem is */

但第二行导致 500 服务器错误。如果我在第二行添加一个字母 x:

rewriterule ^(.*)/$ $1/index.html [L]
rewriterule ^(.*x(?!html))$ $1/index.html [L]

它开始工作,但仅适用于以 x 结尾的目录名称。我尝试用许多不同的东西替换 x。任何比真实字符更复杂的字符(如 [^x] 或 .+)都会导致 500 服务器错误。

而且,为了满足我自己的好奇心,有谁知道为什么添加一个真实的字母会导致服务器错误和完美运行的规则之间产生差异?

[已接受的答案]感谢 Gumbo,我能够使用 rewritecond 近似解决方案:

重写条件 %REQUEST_URI !\.[^/]+$ 重写 (.+) $1/index.html [L]

这可行,但过滤的不仅仅是 .html - 它可能会阻止其他页面。不幸的是,

rewritecond %REQUEST_URI !\.html$

导致服务器错误:

由于可能的配置错误,请求超出了 10 个内部重定向的限制。如有必要,使用“LimitInternalRecursion”增加限制。

我仍然想知道原因:

rewriterule ^(.*(?!html))$ $1/index.html [L]

导致循环。前半部分应该检查它是否以.html结尾。由于后半部分添加了 .html,它的功能似乎相当于:

while(substr($address,-4)!='html') $address.='html'

显然我错过了什么。

【问题讨论】:

如果你能命名服务器错误会更有帮助。 您没有阅读我的编辑说明吗?前瞻断言看起来方向错误。 【参考方案1】:

好吧,为了让它真正发挥作用,您可以只使用否定的后视而不是前瞻:

RewriteRule ^(.*)(?<!html)$ $1/index.html [L]

我不确定为什么添加“x”会使其工作,如果我弄明白了,我会编辑。

【讨论】:

这个建议造成了与我原来的建议相同的 500 服务器错误——而且只有当我在 (?. 之前添加一个随机字母时它才有效【参考方案2】:

关于为什么添加 x 使其工作: 如果替换将匹配正则表达式,则将再次应用 RewriteRule。例如,这会导致错误:

RewriteRule ^(.*)$ $1.rb

因为它会将script 替换为script.rb。这与正则表达式匹配,因此它将script.rb 替换为script.rb.rb,一次又一次......

这在错误日志中有所提示:

Request exceeded the limit of 10 internal redirects due to probable configuration error. Use 'LimitInternalRecursion' to increase the limit if necessary.

在您的示例中,您将 index.html 添加到末尾。当正则表达式末尾有 x 时,它将与您的替换不匹配,替换以 l 结尾。

【讨论】:

它不应该在 andrew 提供的示例中这样做,因为行尾的 [L] 应该会阻止它。 抱歉,不知怎的,我没有看到那里的 [L]。我已经编辑了我的答案,所以它没有说明任何错误。我会多看看它,看看我是否能找出真正的原因。谢谢。 我看到了这个例子是如何创建一个循环的,但我没有看到它如何应用于我的问题——我想要做的是“如果地址不以 .html 结尾, add.html 到地址”。 [L] 对此有何影响? @VirtualBlackFox:我一直在测试,似乎 [L] 并没有停止循环。 [L] 必须阻止应用 other RewriteRules。文档声明“在此处停止重写过程,不再应用任何重写规则。” @Andrew:你想知道为什么在这一行添加 x —— rewriterule ^(.*(?!html))$ $1/index.html [L] —— 让它工作。添加 x 可以防止它循环。否定的前瞻没有做任何事情,因为 .* 已经匹配了整个事情,所以前瞻是针对空性进行测试的。【参考方案3】:

使用RewriteCond 指令检查URL 路径是否不以.html 结尾:

RewriteCond %REQUEST_URI !\.html$
RewriteRule ^(.*[^/])?/?$ $1/index.html [L]

编辑   您正在使用前瞻断言 ((?!…))。但是.* 之后什么都没有(只有一个$)。因此,请尝试使用后向断言:

RewriteRule ^.*$(?<!html) $0/index.html [L]

但请注意,您可能需要 Apache 2.2 才能使用这些断言。

【讨论】:

这个建议造成了 500 服务器错误,我不够专业,无法了解 wny。我将更详细地研究它并稍后编辑此评论。

以上是关于.htaccess 中的重写引擎以捕获不以 html 结尾的文件的主要内容,如果未能解决你的问题,请参考以下文章

WordPress 中的 .htaccess 错误:此处不允许重写引擎

htaccess 重写以包含 #!

htaccess 重写以包含 #!

在htaccess中重写URL时添加.html?

.htaccess 结合 301 重定向和 URI 重写

.htaccess使用URL中的#item重写站点以进行直接文件访问