RewriteRule Последний флаг [L] не работает?

php_flag display_errors 1
php_value auto_prepend_file init.php
RewriteEngine on 
RewriteRule ^$  /id/authenticate [R]
RewriteRule ^login_openid$  /id/login_openid.php [QSA,L]
RewriteRule ^authenticate$  /id/authenticate.php [QSA,L]
RewriteRule ^facebook$  /id/facebook.php [QSA,L]
RewriteRule ^createfromopenid$  /id/createfromopenid.php [QSA,L]

RewriteRule .* - [L,R=403]

Это мой файл .htaccess. В serverconfig я просто AllowOVerride all.

Если я запрашиваю URL http://mydomain.com/id/authenticate, я получаю ошибку 403. Если я удалю последнее правило, оно будет работать. Должна ли талия [L] препятствовать дальнейшим правилам?

Edit:

Мой файл htaccess находится в подпапке "id", поэтому правила работают.

Ответ 1

Правило [L] работает отлично - вы просто не знаете, как это работает .

Когда Apache видит флаг [L] и совпадают правила (переписывание происходит), Apache перейдет к следующей итерации и снова начнет сопоставлять правила all сверху. Флаг [L] означает "не обрабатывать никакие правила ниже в этой итерации".

Да, Документация Apache не является на 100% понятной (что означает, что она может быть улучшена), но дает достаточно информации, чтобы понять это в конечном итоге.


Apache остановит цикл перезаписи в нескольких ситуациях:

  • Совместимые правила (без перезаписи);

  • Соответствует правилу "exit now" (например, RewriteRule .* - [L]);

  • Переписывание происходит, но входной URL-адрес и конечные URL-адреса одинаковы (происходит на 2-й-3-й итерации, когда "плохое" письменное правило переписывает один и тот же URL-адрес на один и тот же URL-адрес.

    Например RewriteRule (.*) /index.php?page=$1 [L]:

    • /hello = > /index.php?page=hello
    • на следующей итерации он перепишет /index.php = > /index.php?page=index.php
    • а на третьей итерации это будет /index.php = > /index.php?page=index.php.., который теперь не имеет смысла);
  • Достигнута предел итерации переименования (по умолчанию = 10) - если вы ввели бесконечный цикл перезаписи (значение управляется LimitInternalRecursion Directive).


Со всей вышеупомянутой информацией я могу сказать, что ваши текущие правила работают как ожидалось. Это означает, что вам нужно изменить логику и избавиться от последнего правила (возможно, справиться с этим моментом в родительском .htaccess.. или обрабатывать его по-другому - все зависит от того, как ваше приложение построено, я не хочу делать дикие догадки).

Ответ 2

Поместите это перед вашим правилом cath all.

RewriteCond %{ENV:REDIRECT_STATUS} !=200

Проблема заключается в том, что после обработки флага [L] все следующие RewriteRules действительно игнорируются, однако файл обрабатывается с начала, теперь с новым URL-адресом.

Это волшебное условие не будет обрабатывать catch all, если файл уже перенаправлен.

PS: Если это не сработает, вам может потребоваться немного настроить условие: 200, !=200, ^., ^$.
Очевидно, что переменная получает значение 200 для перенаправления, но и другие страницы (ошибка и прочее) задают ее для некоторого значения. Теперь это означает, что вы либо проверяете, если он is empty, is not empty, is 200 или is not 200, в зависимости от того, что вам нужно.