Назад | Перейти на главную страницу

Как Apache объединяет несколько совпадающих разделов Location

Я работаю над базовой конфигурацией apache, но не понимаю, как именно apache объединяет разные <Location> разделы, когда несколько из них соответствуют URL входящего запроса. В документация apache в главе «Как объединяются разделы» немного сбивает с толку, когда дело касается порядка / приоритета нескольких совпадающих разделов одного и того же типа.

Например, представьте себе следующую конфигурацию apache (игнорируйте, имеет ли фактическое содержимое смысл или нет, меня интересует только порядок применения каждого правила / раздела):

<Location / >
  ProxyPass http://backend.com/
  Order allow,deny
  Satisfy any
</Location>

<Location /sub/foo>
  Order allow,deny
</Location>

<Location /sub >
  Order deny,allow
  Require valid-user
  Satisfy all
</Location>

<Location /doesnt/match >
  ProxyPass !
</Location>

Теперь, если клиент делает запрос /sub/foobar, какая окончательная конфигурация будет применена к этому запросу?

Применяемая конфигурация эквивалентна:

# All the directives contained in all the matchin Locations in declaration order
ProxyPass http://backend.com/
Order allow,deny
Satisfy any
Order allow,deny
Order deny,allow
Require valid-user
Satisfy all

или, может быть

# same as above, but with longest matching path last
ProxyPass http://backend.com/
Order allow,deny
Satisfy any
Order deny,allow
Require valid-user
Satisfy all
Order allow,deny

или что-то совсем другое.

Спасибо за помощь, я действительно запутался.

Порядок слияния довольно сложен, и исключения легко обнаружить ... Документ apache: "Как объединяются разделы"

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

Порядок типов Directory, DirectoryMatch, Files, и наконец Location. Более поздние совпадения перезаписывают более ранние совпадения. (* ProxyPass и Alias ​​снова обрабатываются по-разному, см. Примечание в конце)

И есть несколько важных исключений из этих правил, которые применяются к использованию ProxyPass и ProxyPass в разделе <Location>. (увидеть ниже)

Итак, из вашего примера выше, запрашивая http://somehost.com/sub/foobar со следующей конфигурацией;

<Location / >
  ProxyPass http://backend.com/
  Order allow,deny
  Satisfy any
</Location>

<Location /sub/foo>
  Order allow,deny
</Location>

<Location /sub >
  Order deny,allow
  Require valid-user
  Satisfy all
</Location>

<Location /doesnt/match >
  ProxyPass !
</Location>

В нем будут собраны следующие директивы ....

  ProxyPass http://backend.com/
  Order allow,deny
  Satisfy any
  Order allow,deny
  Order deny,allow
  Require valid-user
  Satisfy all   

С последующими совпадениями удаляются предыдущие дубликаты, в результате чего:

  ProxyPass http://backend.com/
  Order deny,allow
  Require valid-user
  Satisfy all   

Объяснение
Более поздние совпадения перезаписывают более ранние совпадения, за исключением <Directory> где совпадения обрабатываются в порядке: от самого короткого компонента каталога до самого длинного.

Так, например,
<Directory /var/web/dir>
будет обработано до
<Directory /var/web/dir/subdir>
независимо от того, в каком порядке эти директивы были указаны в конфигурации, и более конкретное совпадение побеждает.

Любое соответствие Location директива всегда будет переопределять предыдущее соответствие Directory директива.

Основная идея заключается в том, что для запроса типа GET /some/http/request.html внутренне он будет переведен в место в файловой системе через Alias, ScriptAlias или для обычного расположения файла под DocumentRoot для соответствующего виртуального хоста.

Таким образом, запрос будет иметь следующие свойства, которые он использует для сопоставления:
Location: /some/http/request.html File: /var/www/html/mysite/some/http/request.html Directory: /var/www/html/mysite/some/http

Затем Apache применит по очереди все Directory соответствует, в порядке специфичности каталога, из конфигурации, а затем, в свою очередь, применяет DirectoryMatch, Files, и наконец Location соответствует в том порядке, в котором они встречаются.

Так Location отменяет Files, который отменяет DirectoryMatch, с сопоставлением путей Directory с самым низким приоритетом. Следовательно, в вашем примере выше запрос на /sub/foobar будет соответствовать первым 3 местоположениям по порядку, следовательно, последний выигрывает для конфликтующих директив.

(Вы правы в том, что из документации неясно, как решаются некоторые из крайних случаев, возможно, что любой allow from * директивы типа будут связаны с соответствующими Order allow,deny, но я этого не проверял. Также что произойдет, если вы сопоставите Satisfy Any но вы ранее собрали Allow from *...)

интересное примечание о ProxyPass и Alias

Просто чтобы раздражать, ProxyPass и Alias похоже, работает в другом направлении .... ;-) Он в основном попадает в первое совпадение, затем останавливается и использует его!

Ordering ProxyPass Directives

The configured ProxyPass and ProxyPassMatch rules are 
checked in the order of configuration. 
The first rule that matches wins. So
usually you should sort conflicting ProxyPass rules starting with the
longest URLs first. Otherwise later rules for longer URLS will be
hidden by any earlier rule which uses a leading substring of the URL.
Note that there is some relation with worker sharing.

For the same reasons exclusions must come before the general 
ProxyPass directives.

так что в основном необходимо указать директивы Alias ​​и ProxyPass, причем в первую очередь наиболее конкретные;

Alias "/foo/bar" "/srv/www/uncommon/bar"
Alias "/foo"     "/srv/www/common/foo"

и

ProxyPass "/special-area" "http://special.example.com" smax=5 max=10
ProxyPass "/" "balancer://mycluster/" stickysession=JSESSIONID|jsessionid nofailover=On

Однако, как указал @orev. У вас может быть директива ProxyPass в директиве Location, и поэтому более конкретный ProxyPass в Location превзойдет любой ранее найденный ProxyPass.