我对 nginx 变量以及它们的工作原理有哪些误解?
第一个位置 /atlas/ 无法将请求发送到上游服务器,并出现以下 nginx 错误:
backoffice | 2024/03/12 22:10:19 [error] 17#17: *9 invalid URL prefix in "", client: 192.168.247.15, server: ~^(backoffice\.)(?<domain>.+)$, request: "GET /atlas/assets/main.css HTTP/1.1", host: "backoffice.local.upowr.io", referrer: "https://backoffice.local.upowr.io/atlas/?latitude=-32.912492&longitude=151.314799&roof_id=c0876d8d-8712-464e-8815-b963d675e8ea&phase_num=1&task_mode=true"
但是几乎等效的位置定义 /atlas-og/ 确实使用变量但不使用第二级间接来配置 proxy_pass 指令,也可以正常工作。
为什么?
location /atlas/ {
rewrite ^/atlas/(.*)$ /$1 break;
set $proxy_pass $ATLAS_UI_ENDPOINT$uri$is_args$args;
proxy_pass $proxy_pass;
}
location /atlas-og/ {
rewrite ^/atlas-og/(.*)$ /$1 break;
proxy_pass $ATLAS_UI_ENDPOINT$uri$is_args$args;
}
更新
location /atlas/ {
rewrite ^/atlas/(.*)$ /$1 break;
proxy_pass $ATLAS_UI_ENDPOINT;
}
set $proxy_pass_outer $ATLAS_UI_ENDPOINT;
location /atlas-outer/ {
rewrite ^/atlas-outer/(.*)$ /$1 break;
proxy_pass $proxy_pass_outer;
}
location /atlas-inner/ {
rewrite ^/atlas-inner/(.*)$ /$1 break;
set $proxy_pass_inner $ATLAS_UI_ENDPOINT;
proxy_pass $proxy_pass_inner;
}
因此,前两个可以工作,但第三个则不可以。
看起来 proxy_pass 不能使用 location 指令中定义的变量,事实上,nginx 对此发出警告:
backoffice | 2024/03/13 00:53:32 [warn] 17#17: *23 using uninitialized "proxy_pass_inner" variable, client: 192.168.247.15, server: ~^(backoffice\.)(?<domain>.+)$, request: "GET /atlas-inner/?latitude=-32.912492&longitude=151.314799&roof_id=c0876d8d-8712-464e-8815-b963d675e8ea&phase_num=1&task_mode=true HTTP/1.1", host: "backoffice.local.upowr.io"
所以问题归结为:为什么 proxy_pass 尊重在服务器范围内设置的变量,而不尊重在位置范围内设置的变量?
答案1
好的,我终于搞定了。
set 指令相对于 rewrite 指令的顺序很重要。
location /atlas-fixed/ {
set $proxy_pass_inner $ATLAS_UI_ENDPOINT;
rewrite ^/atlas-inner/(.*)$ /$1 break;
proxy_pass $proxy_pass_inner;
include includes/location/backoffice.conf;
include includes/policy/do-not-preserve-host-header.conf;
}
然而这是错误的:
location /atlas-broken/ {
rewrite ^/atlas-inner/(.*)$ /$1 break;
set $proxy_pass_inner $ATLAS_UI_ENDPOINT;
proxy_pass $proxy_pass_inner;
include includes/location/backoffice.conf;
include includes/policy/do-not-preserve-host-header.conf;
}
当我看到这条评论时我恍然大悟:
请注意,nginx 配置是声明性的,而不是命令性的,并且 set ... 实际上是在处理重写模块指令期间发生的。这发生在选择适当位置之后和访问检查(尤其是 auth_request)之前。