I'm working on some basic apache configuration, but I don't understand precisely how apache merges different <Location>
sections when several of them match an incoming requests URL. The apache documentation in its "How the sections are merged" chapter is a little bit confusing when it comes to the order/priority of several matching sections of the same type.
For example, imagine the following apache configuration (ignore whether the actual contents make sense or not, I'm only interested in the application order of each rule/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>
Now if a client makes a request to /sub/foobar
, which is the final configuration that will be applied to this request?
Is the applied configuration the equivalent of:
# 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
or maybe
# 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
or something completely different.
Thanks for your help, I'm really confusing.
Best Answer
The order of merging is fairly complicated, and it's easy to be caught out by exceptions... The apache doc is "How the sections are merged"
According to that documentation, the order of merging of sections is done by processing all of the matching entries for each match type in the order that they are encountered in the configuration files, with the last match winning. (with the exception of <Directory>, which is treated in order of path specificity).
The order of types is
Directory
,DirectoryMatch
,Files
, and finallyLocation
. Later matches overwrite earlier matches. (*ProxyPass and Alias are treated differently again, see note at end)And there are several important exceptions to these rules that apply to using ProxyPass, and ProxyPass in a <Location> section. (see below)
So from your example above requesting http://somehost.com/sub/foobar with the follwing config;
It would accumulate the following directives ....
With the later matches eliminating the previous duplicates, resulting in;
Explanation
Later matches overwrite earlier matches with the exception of
<Directory>
where matches are processed in the order: shortest directory component to longest.Any matching
Location
directive will always override a previously matchingDirectory
directive.The basic idea is that for a request like
GET /some/http/request.html
internally it will be translated to a location in the filesystem via anAlias
,ScriptAlias
or for a normal file location under theDocumentRoot
for the VirtualHost that it matched.So a request will have the following properties which it uses for matching:
Location: /some/http/request.html File: /var/www/html/mysite/some/http/request.html Directory: /var/www/html/mysite/some/http
Apache will then apply in turn all of the
Directory
matches, in the order of directory specificity, from the config, and then in turn applyDirectoryMatch
,Files
, and finallyLocation
matches in the order in which they are encountered.So
Location
overridesFiles
, which overridesDirectoryMatch
, with paths matchingDirectory
at the lowest priority. Hence in your example above, a request to/sub/foobar
would match the first 3 Location in order, hence the last one wins for conflicting directives.(You are right that it is not clear from the docs how some of the edge cases are resolved, its possible that any
allow from *
type directives would be connected to the associatedOrder allow,deny
, but I didn't test that. Also what happens if you matchSatisfy Any
but you have previously collected anAllow from *
...)interesting note about ProxyPass and Alias
Just to be annoying,
ProxyPass
andAlias
appears to work in the other direction.... ;-) It basically hits the first match, then stops and uses that!so basically, Alias and ProxyPass directives have to be specified, most specific first;
and
However, as @orev has pointed out. You can have a ProxyPass directive in a Location directive, and so a more specific ProxyPass in a Location will beat out any previously found ProxyPass.