Apache – Fix LocationMatch or ProxyMatch Not Working with RegEx

apache-2.4django

I want to redirect requests for a exact specific location to proxy server but both solutions doesn't work:

<VirtualHost *:80>
  ServerName exmaple.com

<LocationMatch "^/test01$">
  ProxyPreserveHost On
  ProxyPass http://localhost:8000/
  ProxyPassReverse http://localhost:8000/
</LocationMatch>

<ProxyMatch "^/test02$">
  ProxyPreserveHost On
  ProxyPass http://localhost:8000/
  ProxyPassReverse http://localhost:8000/
</ProxyMatch>

</VirtualHost>

Test:

$ curl -I exmaple.com/test01
HTTP/1.1 404 Not Found
Date: Sun, 17 Jun 2018 15:37:10 GMT
Server: Apache
Content-Type: text/html; charset=iso-8859-1

$ curl -I exmaple.com/test02
HTTP/1.1 404 Not Found
Date: Sun, 17 Jun 2018 15:37:13 GMT
Server: Apache
Content-Type: text/html; charset=iso-8859-1

When I remove the RegEx part then it works but I want Apache to display the 404, not the Django development server:

<LocationMatch "/test01">
  ProxyPreserveHost On
  ProxyPass http://localhost:8000/
  ProxyPassReverse http://localhost:8000/
</LocationMatch>

$ curl -I exmaple.com/test01
HTTP/1.1 200 OK
Date: Sun, 17 Jun 2018 15:42:26 GMT
Server: WSGIServer/0.2 CPython/3.6.5
Content-Type: text/html; charset=utf-8
X-Frame-Options: SAMEORIGIN
Content-Length: 12767

$ curl -I exmaple.com/test01/none
HTTP/1.1 404 Not Found
Date: Sun, 17 Jun 2018 15:42:33 GMT
Server: WSGIServer/0.2 CPython/3.6.5
Content-Type: text/html; charset=UTF-8
X-Frame-Options: SAMEORIGIN
Content-Length: 2073

Update: Mon 18 Jun 14:40:59 UTC 2018

So I've done some further research and according to Apache docs:

When used inside a <Location> section, the first argument is omitted
and the local directory is obtained from the <Location>. 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.

So I tried ProxyPassMatch and it works however the RegEx matched is passed to Proxy http://localhost:8000/test01 and this is not what I want.

I can achieve this easily with Nginx:

server {
    listen 80;
    server_name exmaple.com;

    location = /test01/ {
        proxy_pass http://localhost:8000/;
        proxy_set_header Host $host;
    }
}

How I can do something similar with Apache?

Update: Sun 24 Jun 10:46:12 UTC 2018

<LocationMatch "^/test01$">
  Redirect / http://test.com/
</LocationMatch>

$ curl -I exmaple.com/test01
HTTP/1.1 302 Found
Date: Sun, 24 Jun 2018 10:47:04 GMT
Server: Apache
Location: http://test.com/test01
Content-Type: text/html; charset=iso-8859-1

Best Answer

The usual way with Apache of solving the problem of:

  • sending all sub-paths under a root to an upstream
  • hiding upstream-issued 4xx and 5xx errors with static pages

is to use a plain Location block with ProxyPass and ProxyPassReverse, along with ProxyErrorOverride and ErrorDocument. Untested example:

<VirtualHost *:80>
  ServerName exmaple.com
  ProxyErrorOverride On
  ProxyPreserveHost On
  ErrorDocument 404 "That resource was not found"

  <Location /test01>
    ProxyPass http://localhost:8000/
    ProxyPassReverse http://localhost:8000/
  </Location>

</VirtualHost>

See: