2

So usually when creating a nginx location it would look something like this:

location /foo/ {
    proxy_pass http://example.com/;
}

With this setup, requests to /foo/bar are forwarded to http://example.com/bar which is the intended behavior.

However when trying to prevent caching of the domain name example.com or when trying to prevent nginx from crashing if the upstream host is unavailable at startup the only solution seems to be to not use the target directly in the proxy_pass directive, but to instead create a variable containing the target like this:

location /foo/ {
    set          $targetUri http://example.com/;
    proxy_pass   $targetUri;
}

But this totally changes the setup. As soon as proxy_pass contains a variable, it no longer appends anything to the target uri, as the nginx docs describe:

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.

So requests to /foo/bar are simply forwarded to http://example.com/.

When bringing $request_uri into the mix, more than what we want is appended:

location /foo/ {
    set          $targetUri http://example.com$request_uri;
    proxy_pass   $targetUri;
}

Requests to /foo/bar are now forwarded to http://example.com/foo/bar.

The only workaround I have found is to resort to regex patterns for the location:

location ~ ^/foo/(.*)$  {
    set          $targetUri http://example.com/$1$is_args$args;
    proxy_pass   $targetUri;
}

Is there any way to replicate the behavior of proxy_pass when using variables without having to regex-match the location? The reason I want to avoid regex is because the location path is based on a user input from which the location block is generated.

petroni
  • 766
  • 1
  • 13
  • 29

1 Answers1

2

Remove the trailing / from your $targetUri variable so that proxy_pass does not have the "optional URI" part in its value. Then use rewrite...break to duplicate the original behaviour.

For example:

location /foo/ {
    set $targetUri http://example.com;

    rewrite ^/foo(.*)$ $1 break;
    proxy_pass   $targetUri;
}
Richard Smith
  • 45,711
  • 6
  • 82
  • 81
  • Thanks! I'm assuming a regex pattern in just the rewrite directive is less processing power intensive than my solution with the regex pattern in the location block would be? – petroni Nov 12 '21 at 20:09