为什么这个 .htaccess 重写代码没有正确重定向?

Why this .htaccess rewrite code isn't redirecting properly?

它陷入了无休止的重定向循环。如果在最后一个 RewriteRule 中我使用 END 而不是 L 它会按预期工作。为什么会这样,还有其他方法可以解决吗?

RewriteEngine on

#remove tailing slashes
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/+$ / [R,L]

#external redirect: /page.php to /page
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^(.*)\.php$ / [R,L]

#internal redirect: page to page.php
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*?)$ \.php [L]

我的 Apache 版本是 2.4.43


解决方案:

我想我现在明白到底发生了什么。 Mod_rewrite 仅适用于一个版本的 URI,并且只有在我使用 R 标志时更改才会在浏览器中可见。这与@anubhava 的回答一起导致了无休止的重定向循环。换句话说,我认为 RewriteRule ^(.*)\.php$ / [R,L]RewriteRule ^(.*?)$ \.php [L] 实际上不适用于同一版本的 URI。

R标志说明: https://httpd.apache.org/docs/2.4/rewrite/flags.html#flag_r

标志 LEND 的行为不同。 L 标志意味着再次运行重写循环(类似于 while 循环中的 continue)并且 END 循环终止循环(类似于 while 循环中的 break) .

END 标志是在 Apache 2.4 中引入的,它用于防止您当前观察到的重写循环。

当您使用 L 时,您的最后一条规则会在请求 uri 的末尾添加 .php 并且当重写循环再次运行时 #external redirect 规则会从请求 uri 中删除 .php然后最后一条规则再次在请求 uri 的末尾添加 .php。此循环继续并导致无限循环。为防止这种情况,您可以在最后一条规则中使用 END 标志,该标志仅终止 mod_rewrite 当前请求的执行并防止循环行为。

Check: mod_rewrite ruleset processing