skip to Main Content

I’d like to configure Apache as a reverse proxy for that determines the URL to proxy to dynamically by parsing the path of the requested URL.

For example, the URL http://proxy-server/app/your-app would get proxied to http://your-app:8000/ and http://proxy-server/app/your-app/some/path would go to http://your-app:8000/some/path.

The problem I’m running into with the below configuration is that http://proxy-server/app/your-app/ works just fine, but http://proxy-server/app/your-app/some/path gets redirected to http://proxy-server/some/path, which gives a 404 error.

I’ve tried using just mod_proxy like this

ProxyPassMatch "^/app/([^/]+)(?:/(.*))?$" "http://$1:8000/$2"

And I’ve tried it with mod_rewrite

RewriteEngine On
RewriteBase "/app/"
RewriteRule "^([^/]+)/?$" "http://$1:8000/" [E=CONTAINER:$1,P]
RewriteRule "^([^/]+)/(.+)$" "http://$1:8000/$2" [E=CONTAINER:$1,P]

ProxyPassInterpolateEnv On
ProxyPassReverse "/app/" "http://${CONTAINER}:8000/" interpolate

When I curl -D - http://proxy-server/app/your-app I get an HTTP/1.1 200 OK response. When I curl -D - http://proxy-server/app/your-app/some/path I get a HTTP/1.1 301 Move Permanently response with Location: /some/path/.

I’m not sure where the 301 is coming from. Neither Apache nor the app running on that host should be returning a 301, but the Location header made me think it might be that the reverse proxy isn’t set up to correctly rewrite URLs from the remote to which it is proxying, which is why I added the ProxyPassReverse directive above. But I still can’t get it working.

Any insight into how to set this up would be greatly appreciated.

2

Answers


  1. Chosen as BEST ANSWER

    I did have the ProxyPassReverse directive configured incorrectly for this scenario.

    The remote server to which I was proxying (a Django app) was issuing redirects by setting the Location header to a path, not a full URL. So I had to configure Apache like this:

    RewriteEngine On
    RewriteRule "^/app/([^/]+)(?:/.*)?$" - [E=CONTAINER:$1]
    
    ProxyPassInterpolateEnv On
    ProxyPass "/app/${CONTAINER}/" "http://${CONTAINER}:8000/" interpolate
    ProxyPassReverse "/app/${CONTAINER}/" "http://${CONTAINER}:8000/" interpolate
    
    # This guarantees that any Location headers that are just absolute paths
    # get rewritten
    ProxyPassReverse "/app/${CONTAINER}/" "/" interpolate
    

    That last line is the key. It tells Apache that if it gets a Location: /some/path/ header, it should rewrite it as Location: /app/your-app/some/path/. The first ProxyPassReverse directive would have triggered only if Apache had received Location: http://${CONTAINER}:8000/some/path/.


  2. By default, the mod_dir module redirects requests for a directory path that don’t have a trailing slash to one that does. This is controlled by the DirectorySlash directive. Disabling DirectorySlash will turn off this behavior:

    DirectorySlash Off
    

    It may be helpful to specify -v with curl to print verbose output.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search