Implicit upstream not set when proxy_pass is set from a variable
zachwalton opened this issue · 5 comments
Using openresty/1.11.2.3
:
Test config:
daemon off;
http {
server {
listen 8080;
location /upstream {
content_by_lua_block {
ngx.say("upstream")
}
}
location /works {
log_by_lua_block {
local upstream = require 'ngx.upstream'
print(upstream.current_upstream_name())
}
proxy_pass http://localhost:8080/upstream;
}
location /doesnt {
set $proxy_location http://localhost:8080/upstream;
log_by_lua_block {
local upstream = require 'ngx.upstream'
print(upstream.current_upstream_name())
}
proxy_pass $proxy_location;
}
}
}
root@29e1d2b24175:~# curl http://localhost:8080/works
127.0.0.1 - - [18/May/2017:02:51:01 +0000] "GET /upstream HTTP/1.0" 200 9 "-" "curl/7.35.0"
2017/05/18 02:51:01 [notice] 5656#0: *1 [lua] log_by_lua(test.conf:21):3: localhost:8080 while logging request, client: 127.0.0.1, server: , request: "GET /works HTTP/1.1", upstream: "http://127.0.0.1:8080/upstream", host: "localhost:8080"
127.0.0.1 - - [18/May/2017:02:51:01 +0000] "GET /works HTTP/1.1" 200 9 "-" "curl/7.35.0"
root@29e1d2b24175:~# curl http://localhost:8080/doesnt
127.0.0.1 - - [18/May/2017:02:51:14 +0000] "GET /upstream HTTP/1.0" 200 9 "-" "curl/7.35.0"
2017/05/18 02:51:14 [error] 5656#0: *4 failed to run log_by_lua*: log_by_lua(test.conf:21):3: no srv conf for upstream
stack traceback:
[C]: in function 'current_upstream_name'
log_by_lua(test.conf:21):3: in function <log_by_lua(test.conf:21):1> while logging request, client: 127.0.0.1, server: , request: "GET /doesnt HTTP/1.1", upstream: "http://127.0.0.1:8080/upstream", host: "localhost:8080"
127.0.0.1 - - [18/May/2017:02:51:14 +0000] "GET /doesnt HTTP/1.1" 200 9 "-" "curl/7.35.0"
@zachwalton I think it only works with named upstreams, not arbitrary external host names which have no named upstream configuration blocks.
The docs suggest that 'current_upstream_name()' will implicitly include proxy_pass; and indeed it works, just not when setting proxy_pass to the contents of a variable.
I agree that this is a bizarre config that would better be served by named upstreams, so I'm fine with converting our configs over and NTBFing this if you think that's the route to go.
FWIW I was able to work around this with the implicit $proxy_host
variable set by nginx_http_proxy_module
:
http://nginx.org/en/docs/http/ngx_http_proxy_module.html#variables
location /also_works{
set $proxy_location http://localhost:8080/upstream;
log_by_lua_block {
print(ngx.var.proxy_host)
}
proxy_pass $proxy_location;
}
root@29e1d2b24175:~# curl http://localhost:8080/also_works
127.0.0.1 - - [18/May/2017:06:05:32 +0000] "GET /upstream HTTP/1.0" 200 9 "-" "curl/7.35.0"
2017/05/18 06:05:32 [notice] 5744#0: *1 [lua] log_by_lua(test.conf:27):2: localhost:8080 while logging request, client: 127.0.0.1, server: , request: "GET /also_works HTTP/1.1", upstream: "http://127.0.0.1:8080/upstream", host: "localhost:8080"
127.0.0.1 - - [18/May/2017:06:05:32 +0000] "GET /also_works HTTP/1.1" 200 9 "-" "curl/7.35.0"
Feel free to close this if you think it's a weird use case, I'm happy with the workaround.
@zachwalton I was talking about this:
upstream foo.com {
server ...
}
server {
location / {
proxy_pass http://foo.com;
# or
# set $var "foo.com";
# proxy_pass http://$var;
}
}
Makes sense, the problem in our case is that we have a complex config that's already reliant on set $proxy_location http://localhost:8080/upstream; proxy_pass $proxy_location
and changing it to use named upstreams would be a bit onerous.
I was willing to do it but ngx.var.proxy_host
seems to work with variables even when current_upstream_name()
fails. Might be worth updating the docs:
Note that implicit upstreams created by proxy_pass are included, contrary to the output of upstream.get_upstreams().
Changed to:
"Note that implicit upstreams created by proxy_pass are included, contrary to the output of upstream.get_upstreams(), with one exception: setting proxy_pass
to the contents of a variable will not work:
set $proxy_location http://127.0.0.1/upstream;
proxy_pass $proxy_location;
You should instead use named upstreams."