Home > Software design >  Nginx not appending path when using proxy_path
Nginx not appending path when using proxy_path

Time:02-01

I am trying to use Nginx as a reverse proxy for a few backends. It's probably not relevant, but the backends are all hosted within a single Docker network, and the network is being created using docker-compose.

The backends all have the same endpoints that need to be exposed, so to reduce duplicate configuration lines I am trying to use map.

map $http_host $backend {
    host-a.example.com host-a;
    host-b.example.com host-b;
}

server { 
    listen                  443 ssl;
    listen                  [::]:443 ssl;
    server_name             _;
    ssl_certificate         /etc/ssl/cert.pem;
    ssl_certificate_key     /etc/ssl/key.pem;

    location / {
        # there is no DNS resolution if we set proxy_pass targets dynamically, 
        # use the docker internal DNS server
        resolver 127.0.0.11; 
        proxy_pass "http://$backend:8080/";
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

The resolver line has been added as Nginx will otherwise give the error: no resolver defined to resolve *hostname*

However with this configuration I am finding that requests are being sent to the wrong path, for example if I send a request to https://host-a.example.com/books or https://host-a.example.com/books/123/front-cover.jpg the page that is returned is always the root of the site (i.e. https://host-a.example.com/), it seems that for some reason proxy_pass is not including the path with the request to the backend server.

Is there a way that I can make this work with map or do I need to create a separate server block for each of the backends that I want to proxy requests to.

CodePudding user response:

From the proxy_pass documentation:

When variables are used in proxy_pass
. . .
In this case, if URI is specified in the directive, it is passed to the server as is, replacing the original request URI.

You should either remove the trailing / (the documentation calls this the optional URI) :

proxy_pass http://$backend:8080;

Or provide the full URL of the request (conveniently available as a built-in variable) :

proxy_pass http://$backend:8080$request_uri;
  • Related