Проблема перезаписи - 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}

В настоящий момент asset.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] предотвращать выполнение каких-либо дальнейших перезаписаний? Я смущен тем, что происходит здесь.

Любой свет, который вы могли бы пролить на это, будет высоко оценен.

Ответ 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 распознает, что вы перенаправляетесь на ту же страницу и игнорируете свою перезапись после этой точки.

Весь этот процесс происходит потому, что оба условия...

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]