Dynamic proxy_pass to $var with nginx 1.0

2019-01-21 10:59发布

问题:

I am trying to proxy a request to different targets depending on an environment variable. My approach was to put the target url into the custom variable $target and give this to proxy_pass.

But using a variable with proxy_pass doesn't seem to work. This simple config leads to a "502 Bad Gateway" response from nginx.

server {
  listen   8080;
  server_name  myhost.example.com;
  access_log  /var/log/nginx/myhost.access.log;
  location /proxy {
    set $target http://proxytarget.example.com;
    proxy_pass $target;
  }
}

The same config without the variable works:

server {
  listen   8080;
  server_name  myhost.example.com;
  access_log  /var/log/nginx/myhost.access.log;
  location /proxy {
    proxy_pass http://proxytarget.example.com;
  }
}

Is it really not possible to use proxy_pass this way or am I just doing something wrong?

回答1:

I've recently stumbled upon this need myself and have found that in order to use variables in a proxy_pass destination you need to set a resolver as your error.log would most probably contain something like no resolver defined to resolve ...

The solution in my case was to setup the following using Google for DNS resolution:

location ~ /proxy/(.*) {
    resolver 127.0.0.1 [::1];
    proxy_pass http://$1;
}

In your case this should work:

location /proxy {
    resolver 127.0.0.1 [::1];
    set $target http://proxytarget.example.com;
    proxy_pass $target;
}

For resolver 127.0.0.1 to work, you need to install bind9 locally. For Debian/Ubuntu:

sudo apt-get install bind9

More information on nginx and dynamic proxy_passing here: http://www.nginx-discovery.com/2011/05/day-51-proxypass-and-resolver.html

Edit: Replaced the previous public DNS with a local one for security issues.



回答2:

Even though the answer of @soulseekah is complete and correct I want to post an answer for the folks using Nginx inside a cluster of containers, being those inside Kubernetes or Docker Compose.

Basically you have to configure a resolver for Nginx with the address of your actual DNS resolver. For Docker it is always at 127.0.0.11, for Kubernetes refer to this answer

Inside my docker network I was able to successfully configure a dynamic proxy_pass by doing so:

resolver 127.0.0.11 [::1];
set $bcknd http://$http_XBackend$uri$is_args$args;
proxy_pass        $bcknd;

Note that it was fundamental to add the $uri$is_args$args since otherwise the proxy pass didn't take in consideration the path and the querystring.

PS: in my example I am reading an header using the $http_XBackend variable. The header is passed by the client as XBackend: host, here the host should be the hostname where you want to forward your calls. I tried using headers with dashes in them with no luck, I had to use an header without dashes.



回答3:

Stumbled on the same exact issue

proxy_pass wasn't resolving my variables, until we found out our DNS server had a problem

can be checked with this cmd by the way

nslookup your-domain your-dns-ip


回答4:

 location / {
   if ($args ~ "^url=(.+)") { #gets the "url" get parameter
       set $key1 $1;
     proxy_pass $key1;#use the parameter as proxy address
 }
}


标签: proxy nginx