NGINX - Using variable in proxy_pass breaks routing

10.6k views Asked by At

I'm trying to get NGINX's resolver to automatically update the DNS resolution cache, so I'm transitioning to using a variable as the proxy_pass value to achieve that. However, when I do use a variable, it makes all requests go to the root endpoint of the request and cuts off any additional paths of the url. Here's my config:

resolver 10.0.0.2 valid=10s;

server {
    listen 80;
    server_name localhost;

    location /api/test-service/ {
        proxy_redirect     off;

        proxy_set_header   X-Real-IP        $remote_addr;
        proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;

        # If these 2 lines are uncommented, 'http://example.com/api/test-service/test' goes to 'http://example.com/api/test-service/'
        set $pass_url http://test-microservice.example.com:80/;
        proxy_pass  $pass_url;

        # If this line is uncommented, things work as expected. 'http://example.com/api/test-service/test' goes to 'http://example.com/api/test-service/test'
        # proxy_pass  http://test-microservice.example.com:80/;

    }

This doesn't make any sense to me because the hardcoded URL and the value of the variable are identical. Is there something I'm missing?

EDIT: Ah, so I've found the issue. But I'm not entirely sure how to handle it. Since this is a reverse proxy, I need the proxy_pass to REMOVE the /api/test-service/ from the URI before it passes it to the proxy. So..

This:

http://example.com/api/test-service/test

Should proxy to this:

http://test-microservice.example.com:80/test

But instead proxies to this:

http://test-microservice.example.com:80/api/test-service/test

When I'm not using a variable, it drops it no problem. But the variable adds it. Is that just inherently what using the variable will do?

1

There are 1 answers

1
Tarun Lalwani On BEST ANSWER

There is a small point you missed in documentation

When variables are used in proxy_pass:

location /name/ {
  proxy_pass http://127.0.0.1$request_uri;
}

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

So you config needs to be changed to

set $pass_url http://test-microservice.example.com:80$request_uri;
proxy_pass  $pass_url;