使用Apache mod_重写重定向循环(干净URL)
我的情况与中的非常相似(事实上,代码非常相似)。我一直在尝试创建一个使用Apache mod_重写重定向循环(干净URL),apache,.htaccess,mod-rewrite,url-rewriting,Apache,.htaccess,Mod Rewrite,Url Rewriting,我的情况与中的非常相似(事实上,代码非常相似)。我一直在尝试创建一个.htaccess文件,以使用不带文件扩展名的URL,例如https://example.com/file在适当的目录中查找file.html,但也查找https://example.com/file.html重定向(使用HTTP重定向)到https://example.com/file因此只有一个规范URL。使用以下.htaccess: Options +MultiViews RewriteEngine On # Redir
.htaccess
文件,以使用不带文件扩展名的URL,例如https://example.com/file
在适当的目录中查找file.html
,但也查找https://example.com/file.html
重定向(使用HTTP重定向)到<代码>https://example.com/file因此只有一个规范URL。使用以下.htaccess
:
Options +MultiViews
RewriteEngine On
# Redirect <...>.php, <...>.html to <...> (without file extension)
RewriteRule ^(.+)\.(php|html)$ /$1 [L,R]
没有重定向循环。我很想知道差异的来源。这两个文件不是功能相同吗?为什么使用“普通的”RewriteRule
会创建一个循环,而使用%{THE_REQUEST}
不会
请注意,我不是在寻找一种获得干净URL的方法(我可以使用我的文件的第二个版本或上面链接的问题的答案,它查看%{ENV:REDIRECT_STATUS}
),但是出于原因为什么这两种方法有效/无效,因此,这与上面链接的问题不同
注意:我发现仅使用mod_rewrite(无多视图
)会出现同样的问题,因此这似乎不是由于多视图
和mod_rewrite的执行顺序造成的:
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]
选项-多视图
重新启动发动机
##将.php、.html重定向到(不带文件扩展名)
#这很有效。。。
重写cond%{THE_REQUEST}^[A-Z]{3,}\s(+.+)\(php | html)
重写规则^1[L,R]
#但事实并非如此!
#重写规则^(+)\(php| html)$/$1[L,R]
#在文件系统上查找文件扩展名为.php或.html的文件以获取URL
#没有文件扩展名
重写cond%{REQUEST_FILENAME}-D
重写cond%{REQUEST_FILENAME}-F
重写cond%{REQUEST_FILENAME}\.php-f
重写规则^%{REQUEST_FILENAME}.php[L]
重写cond%{REQUEST_FILENAME}-D
重写cond%{REQUEST_FILENAME}-F
重写cond%{REQUEST_FILENAME}\.html-f
重写规则^%{REQUEST_FILENAME}.html[L]
区别在哪里?我希望这两种方法都能起作用,因为对文件的内部重写在.htaccess
的末尾,带有[L]
标志,所以之后不应该发生任何处理或重定向,对吗
# But this doesn’t!
#RewriteRule ^(.+)\.(php|html)$ /$1 [L,R]
此注释规则不起作用并导致重写循环的原因,因为您的其他规则正在添加.html
扩展名,并将%{REQUEST\u URI}
变量更改为/file.html
,从而导致此规则再次执行。从规则中取出.html
,会导致其他规则再次触发。直到达到最大递归限制为止
您还需要了解,mod_rewrite
在循环中运行,直到规则不匹配为止。由于这两条规则都会不断触发,因此,mod_rewrite
会不断循环
基于的规则之所以有效,是因为执行其他重写规则后,请求
变量没有被覆盖。如果查看,您会注意到以下几点:
RewriteRule ^(.+)\.(php|html)$ /$1 [L,R]
在第一个重写规则
,它与(%-解码)匹配
请求的URL路径,或者,在每个目录上下文中(请参见下文)
相对于每个目录上下文的URL路径。后续模式
与上次匹配的重写规则的输出相匹配
因为,一旦您输入以下内容,它将在每个目录的基础上进行匹配:
RewriteRule ^(.+)\.(php|html)$ /$1 [L,R]
REQUEST\u URI
变量改变,mod rewrite再次解析URI。这将导致MultiViews
将URL重写为与此重定向URL匹配的正确文件,并导致循环(每次重写时URI都会更改)
现在,当您放置要匹配的\u REQUEST
变量时,URI可能会在内部重写时更改,但是服务器收到的实际请求将永远不会更改,除非执行重定向。但是[L]
标记不应该停止mod\u rewrite循环吗?为什么它仍然在执行例如RewriteRule^%{REQUEST_FILENAME}.html[L]
?NoL
标志不会停止循环L
标志仅结束当前规则并强制mod_rewrite
再次运行循环。您所说的“当前规则”是指“当前通过.htaccess
文件”吗?否则,该标志将是无用的…是的,这是当前的。它结束当前使用的重写规则
,然后充当mod_rewrite循环的continue
。另外请注意,如果您使用END
(Apache 2.4+提供),那么肯定会终止mod\u rewrite
循环。这里的问题与另一个答案相同:[L]
标记不应该停止mod\u rewrite循环(在我的上一个示例中)?为什么它仍然继续执行例如RewriteRule^%{REQUEST_FILENAME}.html[L]
?即使其他规则仍然匹配,难道它不应该停在[L]
吗?@Socob的has:“因此,如果您在这些上下文中使用重写规则
指令,那么您必须采取明确的步骤来避免规则循环,而不仅仅依赖[L]
标记终止一系列规则的执行,如下所示。”。是的,我知道文档的这一部分。我想理解的是为什么[L]
在这种情况下对我没有帮助。是因为以下的原因吗?在处理重写请求时,可能会再次遇到.htaccess
文件或
部分,因此规则集可能会从一开始就再次运行。最常见的情况是,如果其中一个规则导致重定向(内部或外部)导致请求过程重新开始,则会发生这种情况@Socob啊,是的。我在上一条评论中粘贴文本时删除了错误的段落。@Socob OnceL
标志为encoun