5

FYI - I suspect this has a very obvious/simple answer (I'm new to nginx)

I am using dynamic upstreams as part of my Nginx config. This means using variables in the proxy_pass directive, which instructs nginx to use a resolver instead of crashing/not-booting if an upstream has a problem (unknown host / not connectable).

However, this seems to also change handling of proxy_pass with a URI. Rather than replacing with the request URI with the URI specified in the proxy_pass directive, it appears to ignore the request URI. I'm searching for a method to preserve (or reproduce) the original behavior that allows me to continue using dynamic hosts.

I have attempted to create a minimal example config here:

server {
    listen 80;
    server_name my-server.com;

    # My chosen DNS server (in this case, the Docker DNS)
    resolver 127.0.0.11 valid=30s ipv6=off;

    # This works
    location / {
        set $upstream frontend:8080;
        proxy_pass http://$upstream;
    }

    # This does not work :-( 
    # The original URI (e.g. /api/users/tommy) is ignored, and 
    # all requests to api-server are directly to /api/
    location /api/ {
        set $upstream api-server:8002;
        proxy_pass http://$upstream/api/;
    }
}

One workaround is to drop the URI from the proxy_pass directive and have the upstream server listen on the exact URI needed. This is not ideal, as a core benefit of a gateway server is adding some flexibility to change things independently (rewriting URIs if needed)

For example,

    # This kind of works, but upstream must listen on /api 
    location /api {
        set $upstream api-server:8002;
        proxy_pass http://$upstream;
    }
Hamy
  • 367
  • 3
  • 11

1 Answers1

6

The documentation states that if you use variables in the proxy_pass directive and you specify a URI part, it will be passed upstream "as is".

You will need to capture the part of the URI you need to send upstream. Either use a regular expression location block, for example:

location ~ ^/api(.*)$ {
    set $upstream ...;
    proxy_pass http://$upstream$1;
}

Or use a rewrite...break to change the current URI, for example:

location /api {
    set $upstream ...;
    rewrite ^/api(.*)$ $1 break;
    proxy_pass http://$upstream;
}
Pothi Kalimuthu
  • 5,734
  • 2
  • 24
  • 37
Richard Smith
  • 11,859
  • 2
  • 18
  • 26