Каков приоритет нескольких правил mod_rewrite в нескольких файлах .htaccess?

Я понимаю, что [L], следуя правилу перезаписи, означает, что он "последний", но я не понимаю, что область

Например, когда есть несколько файлов .htaccess, некоторые с [L], какие из них будут применяться?

Пример:

root.com/subdirectory1/subdirectory2

  ^           ^            ^      
  |           |            |
  A           B            C

Если в каждом каталоге есть файл .htaccess...

  • В каком порядке они будут применяться?
  • Если они противоречат друг другу, которые имеют приоритет?
  • Они применяются в серийном номере? Являются ли результаты первого перехода к следующему?
  • Будет ли совпадение в более раннем (или том же) файле, к которому применяется RESULT из более позднего правила?
  • Если в предыдущем файле есть [L], будут рассмотрены другие файлы?

Ответ 1

Флаг [L] действительно означает "последний", но применим только к правилам текущей области. Из вашего вопроса это применимо только к правилам в файле htaccess. Если в подкаталоге есть правила, любые правила в родительском каталоге выкидываются из окна. Они не применяются вообще, если вы не используете директиву RewriteOptions Inherit (которая добавит к концу правил какие-либо правила из родительского файла htaccess).

Учитывая ваш пример:

root.com/subdirectory1/subdirectory2
  ^           ^            ^      
  |           |            |
  A           B            C

Если есть файлы htaccess в A, B и C и переписывать правила во всех 3, если запрашивается http://root.com (ваш каталог "root.com" ), применяются только правила в A. Если кто-то запрашивает http://root.com/subdirectory1, тогда применяются только правила из B, и любые правила в игнорируются (без опции Inherit). Аналогично, если кто-то отправляется на http://root.com/subdirectory1/subdirectory2, тогда применяются только правила в C, если нет вариантов наследования.

Флаг [L] не имеет никакого воспроизведения ни в одном из них, так как область действия здесь находится только в правилах файла htaccess. Также обратите внимание, что [L] не обязательно означает "прекратить переписывание ЗДЕСЬ", так как механизм перезаписи будет зацикливаться до тех пор, пока URI, идущий в двигатель, не перестанет меняться. [L] просто означает прекратить переписывание в текущей итерации цикла перезаписывания.


Немного больше о деталях цикла:

В процессе обработки URL-адресов apache пытается сопоставить URL-адрес файла или ресурса. Множество различных модулей могут участвовать в конвейере обработки, например mod_rewrite или mod_proxy или mod_alias. В любой момент этот URI может быть изменен, помечен как перенаправленный, помечен как проксированный, помечен для выброса ошибки и т.д. Когда URI получает mod_rewrite, механизм перезаписи собирает кучу правил из конфигурации vhost и соответствующий файл htaccess; обратите внимание, здесь есть 2 разных области. Каждая область правил применяется к URI, и если ни одно из правил не соответствует, то mod_rewrite выполняется. Если одно из правил соответствует, есть внутренняя переадресация, то есть URI изменяется, а затем перенаправляется обратно в конвейер обработки и mod_rewrite. Таким образом, тот же диапазон правил снова применяется, и если одно из правил соответствует и применяется, то снова происходит повторение цикла правил. Там есть директива, которую вы можете установить в конфигурации vhost/server под названием LimitInternalRecursion, которая устанавливает предел этих внутренних переадресаций. Если количество циклов перезаписи (то есть перенаправление обратно к себе) превышает этот предел (по умолчанию это 10, я думаю), то вы получите ошибку внутреннего сервера 500.

Это может показаться странным, но есть много примеров для этого. Пример: удалить все _ из URI и заменить на -:

RewriteRule ^(.*)_(.*)$ /$1-$2 [L]

Если URI равен /a_b_c_d_foo, то в первый раз URI будет изменен на /a_b_c_d-foo, затем он будет циклически изменен на `/a_b_c-d-foo, затем снова /a_b-c-d-foo и к 5-му разму времени вы получите /a-b-c-d-foo. Он будет зацикливаться еще раз, но поскольку шаблон ^(.*)_(.*)$ не совпадает, URI проходит через механизм перезаписи и останавливается цикл.

Проблема возникает, когда люди создают правила, которые не учитывают цикл, например: rewrite /<anything> to /foo/<anything>:

RewriteRule ^(.*)$ /foo/$1 [L]

Если URI /bar, то при первом переходе URI на /foo/bar, и это желаемый результат. Но URI получает внутреннюю перенаправленную обратно в механизм перезаписи и повторяет одно и то же правило: /foo/foo/bar, затем снова: /foo/foo/foo/bar и снова: /foo/foo/foo/foo/bar, пока не будет достигнут внутренний предел рекурсии, и вы получите ошибка сервера 500.