Is it possible to mix Alias and AliasMatch with Apache

apache-2.2mod-alias

I have a generic alias match like:

AliasMatch ^/plugins/([^/]*)/(.*) /usr/share/tuleap/plugins/$1/www/$2
<DirectoryMatch "/usr/share/tuleap/plugins/([^/]*)/www/">
...
</DirectoryMatch>

and I want to add a specific configuration for a directory plugin.
I tried to have an Alias first but it doesn't work as expected:

Alias /plugins/git /usr/share/tuleap/plugins/git/www
<Directory /usr/share/tuleap/plugins/git/www>
...
</Directory>

AliasMatch ^/plugins/([^/]*)/(.*) /usr/share/tuleap/plugins/$1/www/$2
<DirectoryMatch "/usr/share/tuleap/plugins/([^/]*)/www/">
...
</DirectoryMatch>

The specific configuration set for "git" seems ignored in favor of the generic one.

Is there a solution to make it works ?

Best Answer

A possible solution would be to write a regular expression that does not match the URLs you want to exclude.

The matching in AliasMatch and some other directives in the Apache Web Server uses PCRE.

Most GNU/Linux distributions have pcre-tools precompiled. This package contains a couple of tools, pcregrep and pcretest, very handy to test Perl compatible regular expressions:

$ cat <<EOF>test.txt
> /plugins/git
> /plugins/foo
> /plugins/bar
> EOF

$ pcregrep '^/plugins/(?!git)' test.txt
/plugins/foo
/plugins/bar

$ pcretest
PCRE version 8.33 2013-05-28

  re> /^\/plugins\/(?!git)/
data> /plugins/git
No match
data> /plugins/foo
 0: /plugins/

In this case, the subexpression (?!git) is known as a negative lookahead:

   Lookahead assertions

       Lookahead assertions start with (?= for positive assertions and (?! for
       negative assertions. For example,

         \w+(?=;)

       matches a word followed by a semicolon, but does not include the  semi-
       colon in the match, and

         foo(?!bar)

       matches  any  occurrence  of  "foo" that is not followed by "bar". Note
       that the apparently similar pattern

         (?!foo)bar

       does not find an occurrence of "bar"  that  is  preceded  by  something
       other  than "foo"; it finds any occurrence of "bar" whatsoever, because
       the assertion (?!foo) is always true when the next three characters are
       "bar". A lookbehind assertion is needed to achieve the other effect.

       If you want to force a matching failure at some point in a pattern, the
       most convenient way to do it is  with  (?!)  because  an  empty  string
       always  matches, so an assertion that requires there not to be an empty
       string must always fail.  The backtracking control verb (*FAIL) or (*F)
       is a synonym for (?!).