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 finally Location
. 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;
<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>
It would accumulate the following directives ....
ProxyPass http://backend.com/
Order allow,deny
Satisfy any
Order allow,deny
Order deny,allow
Require valid-user
Satisfy all
With the later matches eliminating the previous duplicates, resulting in;
ProxyPass http://backend.com/
Order deny,allow
Require valid-user
Satisfy all
Explanation
Later matches overwrite earlier matches with the exception of <Directory>
where matches are processed in the order: shortest directory component to longest.
So for example,
<Directory /var/web/dir>
will be processed before
<Directory /var/web/dir/subdir>
regardless of what order those directives were specified in the config, and the more specific match wins.
Any matching Location
directive will always override a previously matching Directory
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 an Alias
, ScriptAlias
or for a normal file location under the DocumentRoot
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 apply DirectoryMatch
, Files
, and finally Location
matches in the order in which they are encountered.
So Location
overrides Files
, which overrides DirectoryMatch
, with paths matching Directory
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 associated Order allow,deny
, but I didn't test that. Also what happens if you match Satisfy Any
but you have previously collected an Allow from *
...)
interesting note about ProxyPass and Alias
Just to be annoying, ProxyPass
and Alias
appears to work in the other direction.... ;-) It basically hits the first match, then stops and uses that!
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.
so basically, Alias and ProxyPass directives have to be specified, most specific first;
Alias "/foo/bar" "/srv/www/uncommon/bar"
Alias "/foo" "/srv/www/common/foo"
and
ProxyPass "/special-area" "http://special.example.com" smax=5 max=10
ProxyPass "/" "balancer://mycluster/" stickysession=JSESSIONID|jsessionid nofailover=On
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.