重写问题 - L(ast)没有被尊重?

don*_*atJ 1 apache .htaccess mod-rewrite

所以我正在为一个站点开发一个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}
Run Code Online (Sandbox Code Playgroud)

现在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]阻止执行任何进一步的重写?我对这里发生的事情感到困惑.

任何你可以放在这上面的光都会非常感激.

Tim*_*one 7

L标志说这奇怪的是,并不意味着没有更多的规则会被执行"不规则集,执行任何更多的规则" mod_rewrite.

当您指定mod_rewrite一个目录级的指令,例如用.htaccessDirectory一个服务器或虚拟服务器配置的部分,重写来在Apache处理后期.要在这里发挥其魔力,mod_rewrite每次重写URL时都必须执行内部重定向.

由于您的重写可能会指向另一个目录,因此mod_rewrite将其自身指定为此重定向的处理程序,以便它可以通过它在您发送请求的新位置可能找到的任何规则.通常,由于您只处理.htaccess根目录中的单个文件,因此"新"位置中的规则恰好是首先导致重写的规则.

因此,在您的情况下,会发生以下情况:

  • 请求 /css/A01EF
  • mod_rewrite 启动规则集
  • ^css/([0-9a-fA-F]{32})$ -> assets.php?hash=A01EF
  • L flag停止重写并强制内部重定向到 assets.php?hash=A01EF
  • mod_rewrite 再次启动规则集
  • ^([a-zA-Z0-9_.-]+)$- > index.php?url=assets.php&hash=A01EF(你可以QSA在这里使用,顺便说一下)
  • L flag停止重写并强制内部重定向到 index.php?url=assets.php&hash=A01EF

这个循环很可能会继续,但会mod_rewrite识别出你重定向到同一页面并在此之后忽略了你的重写.

整个过程恰好是两个条件的原因......

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
Run Code Online (Sandbox Code Playgroud)

...在.htaccess mod_rewrite规则集中非常常见,因为它们提供了一种简单的方法来确定URL是否已经被重写为预期的真实资源.您可以使用它们,也可以index.php在将请求重写为assets.php以下时排除重写:

RewriteCond %{REQUEST_URI} !^/assets.php
RewriteRule ^([a-zA-Z0-9_.-]+)$ index.php?url=$1&%{QUERY_STRING} [L]
Run Code Online (Sandbox Code Playgroud)