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

发布于 2024-09-14 11:11:53 字数 938 浏览 3 评论 0原文

所以我正在为一个网站开发一个 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

昵称有卵用 2024-09-21 11:11:53

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 识别出您正在重定向到同一个页面并忽略此后的重写。

整个过程恰好就是为什么这两个条件...

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

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

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

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 by mod_rewrite.

When you specify mod_rewrite directives in a per-directory context, like with .htaccess or the Directory 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:

  • Request made for /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 to assets.php?hash=A01EF
  • mod_rewrite starts the ruleset over again
  • ^([a-zA-Z0-9_.-]+)$ -> index.php?url=assets.php&hash=A01EF (you could use QSA here, by the way)
  • L flag stops rewrite and forces internal redirect to index.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...

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

...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 the index.php rewrite when the request has been rewritten to assets.php:

RewriteCond %{REQUEST_URI} !^/assets.php
RewriteRule ^([a-zA-Z0-9_.-]+)$ index.php?url=$1&%{QUERY_STRING} [L]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文