How can LocationMatch and ProxyPassMatch be Combined?

O. R. Mapper picture O. R. Mapper · Feb 4, 2014 · Viewed 15.4k times · Source

I am setting up an Apache 2.4.6 server on an internal machine for testing purposes. One of the things that Apache server is supposed to do is act as a reverse-proxy for another server found on localhost:3030.

The server on localhost:3030 expects one out of a few dataset names on its first path level (for now, the set comprises only of the dataset experimental, but some more will be added later on), so I am trying to pass that through from the requested path.

In my vhost, this works:

<Location /experimental/>
    ProxyPass http://localhost:3030/experimental/
    ProxyPassReverse /
</Location>

For additional datasets, I could copy that and replace experimental with the other dataset names. Obviously, that leads to a lot of code duplication/redundancy, which is both a source of errors and a maintenance horror.

Therefore, I would like to become somewhat more flexible and treat several datasets in a single such block. This should be possible with the LocationMatch directive.

As indicated by this comment and this page, I need to replace ProxyPass ProxyPassMatch when using that inside a LocationMatch block. Essentially, the docs state the same:

The same will occur inside a LocationMatch section, however ProxyPass does not interpret the regexp as such, so it is necessary to use ProxyPassMatch in this situation instead.

The LocationMatch docs explain:

From 2.4.8 onwards, named groups and backreferences are captured and written to the environment with the corresponding name prefixed with "MATCH_" and in upper case. This allows elements of URLs to be referenced from within expressions and modules like mod_rewrite. In order to prevent confusion, numbered (unnamed) backreferences are ignored. Use named groups instead.

That information is only valid as of Apache 2.4.8, which is presumeably why the following does not work on my 2.4.6 installation:

<LocationMatch /(?<dataset>experimental)/>
    ProxyPassMatch http://localhost:3030/%{env:MATCH_DATASET}/
    ProxyPassReverse /
</LocationMatch>

On the other hand, this page and that posting imply that the numerical group index ($1) can be used (as the help text is valid only as of httpd 2.4.8, my suspicion / hope is that the numerical reference works before 2.4.8 (?)

In any case, I have tried this:

<LocationMatch "/(experimental)/">
    ProxyPassMatch http://localhost:3030/$1/
    ProxyPassReverse /
</LocationMatch>

yet according to the logs, the internal call invokes http://localhost:3030/$1/ instead of http://localhost:3030/experimental/ when requesting the experimental path on the vhost URL.

The ProxyPassMatch docs only say:

When used inside a LocationMatch section, the first argument is omitted and the regexp is obtained from the LocationMatch.

However, the text does not bother to provide an example for how to combine LocationMatch and ProxyPassMatch. What am I doing wrong?

Answer

cghislai picture cghislai · Jul 7, 2018

The doc also states When the URL parameter doesn't use any backreferences into the regular expression, the original URL will be appended to the URL parameter., which seems to be your case. Further more, you are missing the host in your ProxyPassReverse directive.

This should work just fine:

<LocationMatch "^/experimental/.*$">
    ProxyPassMatch http://localhost:3030
    ProxyPassReverse http://localhost:3030
</LocationMatch>