Comment Apache fusionne-t-il plusieurs sections d'emplacement correspondantes?

35

Je travaille sur une configuration de base d'Apache, mais je ne comprends pas très bien comment Apache fusionne différentes <Location>sections lorsque plusieurs d'entre elles correspondent à une URL de requête entrante. La documentation d'Apache dans son chapitre "Comment les sections sont fusionnées" est un peu déroutante quand il s'agit de l'ordre / priorité de plusieurs sections correspondantes du même type.

Par exemple, imaginez la configuration apache suivante (ignore si le contenu réel a un sens ou non, je ne m'intéresse qu'à l'ordre d'application de chaque règle / section):

<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>

Maintenant, si un client fait une demande à /sub/foobar, quelle est la configuration finale qui sera appliquée à cette demande?

La configuration appliquée est-elle l'équivalent de:

# 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

ou peut-être

# 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

ou quelque chose de complètement différent.

Merci pour votre aide, je suis vraiment déroutant.

LordOfThePigs
la source

Réponses:

44

L'ordre de fusion est assez compliqué, et il est facile de se faire attraper par des exceptions ... Le doc d'Apache est " Comment les sections sont fusionnées "

Selon cette documentation, l'ordre de fusion des sections est traité en traitant toutes les entrées correspondantes pour chaque type de correspondance dans l'ordre indiqué dans les fichiers de configuration, puis en passant au type suivant (à l'exception de <Répertoire >, qui est traité par ordre de spécificité du chemin).

L'ordre des types est Directory, DirectoryMatch, Fileset enfin Location. Les matchs ultérieurs écrasent les matchs précédents. (* ProxyPass et Alias ​​sont à nouveau traités différemment, voir la note à la fin)

Et il existe plusieurs exceptions importantes à ces règles qui s'appliquent à l'utilisation de ProxyPass et de ProxyPass dans une section <Location>. (voir ci-dessous)

Donc, à partir de votre exemple ci-dessus demandant http://somehost.com/sub/foobar avec la configuration suivante;

<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>

Cela accumulerait les directives suivantes ...

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

Avec les correspondances ultérieures, éliminant les doublons précédents, résultant en;

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

Explication Correspondances
ultérieures écraser les correspondances antérieures à l'exception des <Directory>correspondances dans l'ordre: composant du répertoire le plus court au plus long.

Ainsi, par exemple,
<Directory /var/web/dir>
sera traité avant
<Directory /var/web/dir/subdir>
quel que soit l'ordre dans lequel ces directives ont été spécifiées dans la configuration, et la correspondance la plus spécifique gagne.

Toute Locationdirective correspondante remplacera toujours une Directorydirective précédemment correspondante .

L'idée de base est que, pour une requête de type GET /some/http/request.htmlinterne, elle sera traduite vers un emplacement du système de fichiers via un Alias, ScriptAliasou pour un emplacement de fichier normal sous le DocumentRootpour le VirtualHost correspondant.

Ainsi, une demande aura les propriétés suivantes qu'elle utilisera pour la correspondance:
Location: /some/http/request.html File: /var/www/html/mysite/some/http/request.html Directory: /var/www/html/mysite/some/http

Apache appliquera ensuite à son tour tous les Directorymatches, dans l'ordre de la spécificité du répertoire, de la configuration, puis à son tour appliquer DirectoryMatch, Fileset enfin Locationcorrespond à l'ordre dans lequel ils sont rencontrés.

Donc, les Locationsubstitutions Files, qui remplacent DirectoryMatch, avec les chemins correspondant Directoryà la priorité la plus basse. Par conséquent, dans votre exemple ci-dessus, une requête to /sub/foobarcorrespondrait aux 3 premiers emplacements dans l'ordre, d'où le dernier à gagner pour les directives en conflit.

(Vous avez raison de dire que la documentation n'indique pas comment certains cas d'extrémité sont résolus, il est possible que toutes allow from *les directives de type soient connectées à l'associé Order allow,deny, mais je n'ai pas testé cela. De plus, que se passe-t-il si Satisfy Anyvous ont déjà recueilli un Allow from *...)

note intéressante sur ProxyPass et Alias

Juste pour être ennuyeux, ProxyPasset Aliassemble fonctionner dans l'autre sens .... ;-) Il frappe essentiellement le premier match, puis s'arrête et utilise ça!

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.

Donc, fondamentalement, les directives Alias ​​et ProxyPass doivent être spécifiées, les plus spécifiques en premier;

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

et

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

Cependant, comme l'a souligné @orev. Vous pouvez avoir une directive ProxyPass dans une directive Location. Ainsi, un ProxyPass plus spécifique dans un Location vaincra tout ProxyPass précédemment trouvé.

Tom H
la source
3
Merci d'avoir signalé l'avertissement concernant la commande de directives ProxyPass. M'a sauvé beaucoup de maux de tête
Jeremy French
2
En ce qui concerne ProxyPass "travailler dans l’autre sens" , cela n’est vrai que s’ils se trouvent en dehors d’un <Location>. À l'intérieur de a <Location>, les règles de fusion <Location>sont suivies, ce qui signifie que vous voulez que vos <Location>directives les moins spécifiques passent avant les plus spécifiques. Cela permet aux plus spécifiques de remplacer les directives moins spécifiques. Vous ne pouvez en avoir qu'un ProxyPasspar <Location>.
orev