18

I'd like to proxy a request to another server using proxy_pass while removing the matched path prefix. I believe that one way of doing this is as follows;

location /a/ {
  proxy_pass https://website.com/
}

E.g. a request to http://localhost/a/b.html would be proxied to https://website.com/b.html.

As far as I am aware the issue with this in non-commercial versions on NGINX is that the DNS A record for website.com would be loaded and cached forever on startup. I've seen a technique to workaround this by using a variable such as $request_uri in the proxy_pass directive, thus forcing NGINX to re-resolve the DNS according to the TTL of the record.

E.g.

location /a/ {
  rewrite ^/a/(.*) /$1  break;
  proxy_pass https://website.com/$request_uri
}

Unfortunately, it seems that the above doesn't work as it seems to still pass the /a/ prefix to the upstream.

Essentially all I want to achieve here is to proxy a request while removing the path prefix in such a way that DNS records are not cached forever.

Thanks.

David
  • 7,652
  • 21
  • 60
  • 98

1 Answers1

49

I'm not sure where you've seen it, but just using specifically $request_uri is certainly not going to magically make nginx resolve the domain names for you dynamically.

Perhaps what was suggested was explicitly using the variables, such as $uri (which is a different variable), on the assumption that when the variables are in use, then the domain name is resolved individually each time, without any caching? I don't confirm or deny whether such assumption is correct, but the following will at least get rid of /a for you.

location /a/ {
  rewrite ^/a/(.*) /$1  break;
  proxy_pass https://website.com/$uri$is_args$args;
}

(Note that if it's indeed implemented not to cache the domain name, then you might as well want to run a local resolver, otherwise, the extra latency and downtime of your hosting provider's DNS will immediately affect your site, not to mention the possible DNS query limits of their servers.)


Perhaps a better solution would be to periodically restart nginx to automatically pick up the changes in DNS? E.g., nginx -s reload or kill -HUP? As explained in http://nginx.org/en/docs/beginners_guide.html#control and http://nginx.org/en/docs/control.html#reconfiguration, nginx never stops processing any requests during reload, so it should be a safe operation; and it'll most likely result in DNS being flushed, too.

cnst
  • 25,870
  • 6
  • 90
  • 122
  • Thank you for your reply, I will test this today and if it works fine I will mark this answer accepted. I found the previous advice regarding the resolution [here](http://gc-taylor.com/blog/2011/11/10/nginx-aws-elb-name-resolution-resolvers). I'm pretty confident that this had the "intended" effect as far as resolving DNS goes, because previously without this the upstream would reliably no longer be available every few days or so and I would need to restart. I've had it running like this for over 3 months now with no restarts and I've not encountered any DNS issues since making that change. – David Oct 25 '15 at 10:33
  • 2
    Oh, yeah, if nginx keeps a cache for 5 minutes of all the hostnames it resolves in the presence of any variables within proxy_pass, that would make sense; it's actually even documented that way, but it's not very explicit! learn every day! :-) so, I guess the above should work, and you should even remove `/` after `.com`, e.g., should be `.com$uri` – cnst Oct 26 '15 at 03:28
  • So preliminary tests seem to work ok with your original suggestion `rewrite ^/a/(.*) /$1 break; proxy_pass https://website.com/$uri$is_args$args;)` but not ok with just `.com$uri` (the query parameters are not propagated to the upstream. I'll stick with the first suggestion. thanks for the replies! – David Oct 27 '15 at 14:47
  • 2
    @DavidGoate, I said to omit just the `/` before `$uri`, not the whole thing around it! if you omit `$is_args$args`, then of course the query won't be propagated, as it's absent from `$uri`, only being already present in `$request_uri`, which, as already mentioned, is an entirely different variable! – cnst Oct 27 '15 at 22:39
  • 1
    Thanks for your answer! It did the job – ganjim Jan 23 '20 at 07:43