带有变量的 Nginx proxy_pass 很难理解。有人能解释一下如何实现下面的场景吗?
#first call /?proxytohost=http://blahblah.com
#second redirection to /
#third call /home
location / {
if ($arg_proxytohost) {
set $proxytohost $arg_proxytohost;
rewrite ^.*$ / break;
}
proxy_pass https://$proxytohost; #first call it may recognize, third call definitely it cant
proxy_intercept_errors on;
error_page 301 302 307 = @handle_redirects;
}
location @handle_redirects {
set $saved_redirect_location '$upstream_http_location';
proxy_set_header Host $proxy_host;
proxy_pass $proxytohost$saved_redirect_location; #this has proxytohost, i dont think it can recognize the variable here
}
编辑:
想要反向代理几个动态实例(a.blahblah.com、b.blahblah.com 等)。每个服务实例都有多个重定向,我需要在其中存储 cookie 并重定向它们(这就是我有 @handle_redirects 部分的原因)。
$proxytohost
如果我将位置声明上方的变量设置为 a.blahblah.com,那么它就会按预期工作。
但是如果我想将其$proxytohost
作为动态参数发送到第一个请求,然后将其设置为变量,然后通过 proxy_pass 它,那么它就不起作用。
例如,假设我的 nginx 在 中运行localhost:8080
,那么我的期望是
如果我卷曲如下
http://localhost:8080/?proxytohost=a.blahblah.com?authToken=aksdfkj
使用该令牌进行身份验证并重定向到主页后,它应该带我到主页,
http://localhost:8080/home
在这种情况下,/home
是由 提供的内容https://a.blahblah.com/home
。
答案1
这是行不通的。
如果我理解正确的话,您希望在连续请求时代理到同一主机。Nginx 独立处理请求。因此,在第 2 次和第 3 次请求中,如果$arg_proxytohost
不存在,则使用您提供的默认值。
我建议使用 Cookies。下面是一个小例子。
这需要在 http{} 中,可以在 conf.d 中的一个单独的文件中
map $cookie_p_host $p_host {
default $cookie_p_host;
"" $host;
}
接下来我们有进入服务器的位置{}
location ~ /proxy/sethost/(?<p_host>.*) {
add_header Set-Cookie 'p_host=$p_host;path=/proxy';
add_header Content-type text/html;
return 200 'cookie was "$cookie_p_host"<br>now set to "$p_host"';
}
location ~ /proxy(?<p_uri>.*) {
resolver 8.8.8.8 ;
resolver_timeout 5s;
proxy_set_header Host $p_host;
proxy_pass http://$p_host$p_uri;
}
用法/说明:
映射
映射用于避免令人讨厌的 if 语句。如果设置了 cookie,它将用作主机名(无论正确与否,我们都不会检查或关心)。如果未设置(null/empty),我们将使用 $host 变量。您可以将其更改为您想要的任何内容。
第一个位置
(http://localhost:8080/proxy/sethost/example.com) 将设置一个将主机设置为 example.com 的 cookie。/proxy/sethost/ 之后的任何内容都将算作主机名!
第二个地点
(http://localhost:8080/proxy) 现在将代理到 example.com。如果配置中其他地方尚未添加动态查找解析器,则添加一个解析器。我们需要将代理请求的 Host 标头设置为请求的标头,然后我们就可以开始了。
希望这能有所帮助。重定向巫术是另一个话题
答案2
不使用解析器的情况下在 URL 中使用变量进行 proxy_pass 仅在 nginx-plus(商业版本)上可用
添加解析器意味着您将负责将其指向能够理解您的 URL 的 DNS。
我尝试了很长时间才让它在免费版本上运行:
proxy_pass http://$myvariable:8081;
这是 nginx 表示“付钱给我”的方式。
答案3
您可以将 if 指令更改为位置块之外,其含义相同。
if ($arg_proxytohost) {
set $proxytohost $arg_proxytohost;
rewrite ^.*$ / break;
}
location / {
proxy_pass https://$proxytohost; #first call it may recognize, third call definitely it cant
proxy_intercept_errors on;
error_page 301 302 307 = @handle_redirects;
}