Як Apache об'єднує декілька відповідних розділів Location


35

Я працюю над базовою конфігурацією 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

або щось зовсім інше.

Дякую за допомогу, я дуже заплутався.

Відповіді:


44

Порядок злиття досить складний, і його легко викрити винятками ... Apache doc - " Як злиття розділів "

Відповідно до цієї документації, порядок об'єднання розділів виконується шляхом обробки всіх відповідних записів для кожного типу відповідності в порядку, з яким вони зустрічаються у файлах конфігурації, а потім переходом до наступного типу (за винятком <Каталог >, який обробляється в порядку специфіки шляху).

Порядок типів Directory, DirectoryMatch, Filesі , нарешті Location. Пізніші відповідники переписують попередні збіги. (* ProxyPass та псевдоніми знову трактуються по-різному, див. Примітку в кінці)

І є кілька важливих винятків із цих правил, які стосуються використання ProxyPass та ProxyPass у розділі <Location>. (Дивись нижче)

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

<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що він відповідає VirtualHost.

Таким чином, запит матиме такі властивості, які він використовує для відповідності:
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 та псевдоніми

Просто дратує, 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 у директиві про розташування, і тому більш конкретний ProxyPass у розташуванні буде вибивати будь-який раніше знайдений ProxyPass.


3
Дякуємо, що позначили попередження про замовлення директив ProxyPass. Врятував мені сильний головний біль
Джеремі Французький

2
Що стосується ProxyPass "роботи в іншому напрямку" , це справедливо лише в тому випадку, якщо вони знаходяться поза межами <Location>. Всередині а дотримуються <Location>правил злиття <Location>, тобто ви хочете, щоб ваші найменш конкретні <Location>директиви виходили перед більш конкретними. Це дозволяє більш конкретним директивам змінювати менш конкретні директиви. Ви можете мати лише одного ProxyPassна одного <Location>.
орев
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.