重写问题 - L(ast) 不被尊重?
所以我正在为一个网站开发一个 CSS/JS 压缩系统,该系统基本上具有以下 htaccess
RewriteEngine On
...
RewriteRule ^css/images/(.*)$ images/site/$1?%{QUERY_STRING} [L]
RewriteRule ^css/([0-9a-fA-F]{32})$ assets.php?hash=$1 [L]
RewriteCond %{HTTP_HOST} ^www.site.com [NC]
RewriteRule ^(.*)$ http://site.com/$1 [L,R=301]
RewriteRule ^([a-zA-Z0-9_.-]+)$ index.php?url=$1&%{QUERY_STRING} [L]
php_flag register_globals off
php_flag magic_quotes_gpc off
php_flag register_long_arrays off
# 404 Handler
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?url=$1&%{QUERY_STRING}
现在,assets.php 没有接收哈希调用,而是 index.php - 如果我删除行 RewriteRule ^([a-zA-Z0-9_.-]+)$ index.php?url=$1&%{QUERY_STRING} [L]
它工作正常,但我不知道为什么 - 不应该资产重写上的 [L] 标志 RewriteRule ^css/([0-9a-fA-F]{32})$ assets.php?hash=$1 [L]
防止进一步重写被处决?我对这里发生的事情感到困惑。
如果您能对此有所了解,我们将不胜感激。
So I'm working on a CSS/JS compressing system for a site, that has basically the following htaccess
RewriteEngine On
...
RewriteRule ^css/images/(.*)$ images/site/$1?%{QUERY_STRING} [L]
RewriteRule ^css/([0-9a-fA-F]{32})$ assets.php?hash=$1 [L]
RewriteCond %{HTTP_HOST} ^www.site.com [NC]
RewriteRule ^(.*)$ http://site.com/$1 [L,R=301]
RewriteRule ^([a-zA-Z0-9_.-]+)$ index.php?url=$1&%{QUERY_STRING} [L]
php_flag register_globals off
php_flag magic_quotes_gpc off
php_flag register_long_arrays off
# 404 Handler
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?url=$1&%{QUERY_STRING}
Right now assets.php isn't receiving the hash call, but rather index.php - if I remove the line RewriteRule ^([a-zA-Z0-9_.-]+)$ index.php?url=$1&%{QUERY_STRING} [L]
it works fine but I don't know why - shouldn't the [L] flag on the assets rewrite RewriteRule ^css/([0-9a-fA-F]{32})$ assets.php?hash=$1 [L]
prevent any further rewrites from being executed? I'm confused by whats happening here.
Any light you could shed on this would be much appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
L
标志表示“不再执行规则集中的任何规则”,奇怪的是,这并不意味着mod_rewrite
不会执行更多规则。当您在每个目录上下文中指定
mod_rewrite
指令时,例如使用.htaccess
或服务器或虚拟服务器配置的Directory
部分,重写出现在 Apache 处理阶段的后期。为了发挥它的魔力,mod_rewrite
必须在每次重写您的 URL 时执行内部重定向。由于您的重写可能会将您指向不同的目录,因此
mod_rewrite
将自己指定为此重定向的处理程序,以便它可以遍历在您将请求发送到的新位置可能找到的任何规则。通常,由于您只处理根目录中的单个.htaccess
文件,因此“新”位置中的规则恰好是首先导致重写的规则。因此,在您的情况下,会发生以下情况:
/css/A01EF
发出的请求mod_rewrite
启动规则集^css/([0-9a-fA-F ]{32})$ -> assets.php?hash=A01EF
L
标志停止重写并强制内部重定向到assets.php?hash=A01EF
mod_rewrite
启动再次规则集^([a-zA-Z0-9_.-]+)$
->index.php?url=assets.php&hash=A01EF
(顺便说一句,您可以在此处使用QSA
)L
标志停止重写并强制内部重定向到index.php?url=assets.php&hash=A01EF
此循环很可能会继续,但
mod_rewrite
识别出您正在重定向到同一个页面并忽略此后的重写。整个过程恰好就是为什么这两个条件...
...在
.htaccess
mod_rewrite
规则集中如此常见,因为它们提供了一种简单的方法来确定是否URL 已被重写为预期的真实资源。您可以使用它们,或者当请求被重写为assets.php
时,您可以排除index.php
重写:The
L
flag says "do not execute any more rules in the ruleset," which oddly enough does not imply that no more rules will be executed bymod_rewrite
.When you specify
mod_rewrite
directives in a per-directory context, like with.htaccess
or theDirectory
section of a server or virtual server configuration, the rewrite comes late in the Apache processing stage. To do its magic here,mod_rewrite
has to perform an internal redirect every time that your URL is rewritten.Since your rewrite could point you to a different directory,
mod_rewrite
assigns itself as the handler for this redirection so that it can go through whatever rules it may find at the new location you've sent the request to. Often, since you're only dealing with a single.htaccess
file in your root, the rules in the "new" location happen to be the ones that caused the rewrite in the first place.So, in your case, the following happens:
/css/A01EF
mod_rewrite
starts the ruleset^css/([0-9a-fA-F]{32})$ -> assets.php?hash=A01EF
L
flag stops rewrite and forces internal redirect toassets.php?hash=A01EF
mod_rewrite
starts the ruleset over again^([a-zA-Z0-9_.-]+)$
->index.php?url=assets.php&hash=A01EF
(you could useQSA
here, by the way)L
flag stops rewrite and forces internal redirect toindex.php?url=assets.php&hash=A01EF
It's likely that this loop would continue, but
mod_rewrite
recognizes that you're redirecting to the same page and ignores your rewrite after this point.This whole process happens to be why the two conditions...
...are so common in
.htaccess
mod_rewrite
rulesets, given that they provide an easy way to determine if the URL has already been rewritten to the intended real resource. You could use them, or you can exclude theindex.php
rewrite when the request has been rewritten toassets.php
: