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

时间:2010-08-14 05:10:48

标签: 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}

现在assets.php没有收到哈希调用,而是index.php - 如果我删除了行RewriteRule ^([a-zA-Z0-9_.-]+)$ index.php?url=$1&%{QUERY_STRING} [L]

它工作正常但我不知道为什么 - 资产重写RewriteRule ^css/([0-9a-fA-F]{32})$ assets.php?hash=$1 [L]上的[L]标志是否应该阻止执行任何进一步的重写?我对这里发生的事情感到困惑。

你可能会对此有所了解。非常感谢。

1 个答案:

答案 0 :(得分: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标志停止重写并强制内部重定向到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会识别出你重定向到同一页面并在此之后忽略了你的重写。

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

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

...在.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]