使用Apache mod_rewrite重新定向循环(干净的URL)

时间:2015-11-23 02:06:11

标签: apache .htaccess mod-rewrite url-rewriting

我的情况与this question中的情况非常相似(事实上,代码非常相似)。我一直在尝试创建一个.htaccess文件来使用没有文件扩展名的网址,例如https://example.com/file在相应的目录中找到file.html,但https://example.com/file.html重定向(使用HTTP重定向)到https://example.com/file,因此只有一个规范网址。使用以下.htaccess

Options +MultiViews
RewriteEngine On

# Redirect <...>.php, <...>.html to <...> (without file extension)
RewriteRule ^(.+)\.(php|html)$ /$1 [L,R]

我一直在进行重定向循环,就像上面提到的问题一样。 (就我而言,找到相应的文件是通过MultiViews而不是单独的RewriteRule来实现的。)

然而,a solution adopted from this answer

Options +MultiViews
RewriteEngine On

# Redirect <...>.php, <...>.html to <...> (without file extension)
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s(.+)\.(php|html)
RewriteRule ^ %1 [L,R]

没有重定向循环。我有兴趣找出差异的来源。这两个文件在功能上是否相同?为什么使用“普通”RewriteRule会创建一个循环,而使用%{THE_REQUEST}却没有?

请注意,我正在寻找获取干净网址的方法(我可以使用我的文件的第二个版本或上​​面链接的问题的答案,其中查看{{1 }}),但是对于原因为什么这两种方法有效/不起作用,所以这与上面链接的问题不同。

注意:我只使用mod_rewrite(没有%{ENV:REDIRECT_STATUS})看到同样的问题,所以它似乎不是由于{{1}的执行顺序}和mod_rewrite:

MultiViews

区别在哪里?我希望这两种方法都能正常工作,因为文件的内部重写位于MultiViews的最后,带有Options -MultiViews RewriteEngine On ## Redirect <...>.php, <...>.html to <...> (without file extension) # This works... RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s(.+)\.(php|html) RewriteRule ^ %1 [L,R] # But this doesn’t! #RewriteRule ^(.+)\.(php|html)$ /$1 [L,R] # Find file with file extension .php or .html on the filesystem for a URL # without file extension RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME}\.php -f RewriteRule ^ %{REQUEST_FILENAME}.php [L] RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME}\.html -f RewriteRule ^ %{REQUEST_FILENAME}.html [L] 标志,因此之后不应该进行任何处理或重定向,对吗?

2 个答案:

答案 0 :(得分:1)

# But this doesn’t!
#RewriteRule ^(.+)\.(php|html)$ /$1 [L,R]

此注释规则不起作用并导致重写循环的原因是因为您的其他规则正在添加.html扩展名并将%{REQUEST_URI}变量更改为/file.html,从而导致此规则再次执行。从规则中取出.html会导致其他规则再次触发。这一直持续到达到最大递归限制。

您还需要了解mod_rewrite在循环中运行,直到规则不匹配为止。由于两个规则都会继续触发,因此mod_rewrite会保持循环。

基于THE_REQUEST的规则之所以有效,是因为THE_REQUEST变量在执行其他重写规则后不会被覆盖。

答案 1 :(得分:1)

如果您查看RewriteRule directive's documentation,您会注意到以下内容:

  

在第一个RewriteRule上,它与(%-decoded)匹配   请求的URL路径,或者,在每个目录上下文中(见下文),   相对于每个目录上下文的URL路径。后续模式   与最后匹配的RewriteRule的输出匹配。

因为,一旦你输入以下内容,它将在每个目录的基础上进行匹配:

RewriteRule ^(.+)\.(php|html)$ /$1 [L,R]

REQUEST_URI变量发生变化,mod-rewrite再次解析URI。这会导致MultiViews将URL重写为与此重定向URL匹配的正确文件并导致循环(每次重写时URI都会更改)。

现在,当您将THE_REQUEST变量用于匹配时,URI可能会在内部重写时发生更改,但服务器接收的实际请求将永远不会更改,除非执行重定向