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?
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_pass
ing 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.
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.
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
location / {
if ($args ~ "^url=(.+)") { #gets the "url" get parameter
set $key1 $1;
proxy_pass $key1;#use the parameter as proxy address
}
}