使用 nginx 1.0 动态 proxy_pass 到 $var

发布于 2024-11-02 20:10:51 字数 659 浏览 1 评论 0原文

我正在尝试根据环境变量将请求代理到不同的目标。我的方法是将目标 url 放入自定义变量 $target 中,并将其传递给 proxy_pass。

但使用 proxy_pass 变量似乎不起作用。这个简单的配置会导致 nginx 发出“502 Bad Gateway”响应。

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;
  }
}

没有变量的相同配置也有效:

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

是否真的无法以这种方式使用 proxy_pass 或者我只是做错了什么?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

人│生佛魔见 2024-11-09 20:10:51

我最近自己偶然发现了这种需求,并发现为了在 proxy_pass 目标中使用变量,您需要设置一个解析器,因为您的 error.log 很可能包含诸如 no reverver Defined to resolve ... 之类的内容

在我的例子中,解决方案是使用本地 DNS 进行以下设置以进行 DNS 解析:

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

在您的例子中,这应该有效:

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

要使解析器 127.0.0.1 正常工作,您需要在本地安装 bind9。
对于 Debian/Ubuntu:

须藤apt-get安装bind9

有关 nginx 和动态 proxy_pass 的更多信息,请访问:http://www.nginx-discovery.com/2011/05/day-51-proxypass-and-resolver.html

编辑:
为了安全问题,将之前的公共 DNS 替换为本地 DNS。

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 a local DNS 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.

心如狂蝶 2024-11-09 20:10:51

尽管 @soulseekah 的答案是完整且正确的,但我想为在容器集群中使用 Nginx 的人们(即 Kubernetes 或 Docker Compose 中的容器)发布一个答案。

基本上,您必须使用实际 DNS 解析器的地址为 Nginx 配置解析器。对于 Docker,始终位于 127.0 .0.11,对于 Kubernetes,请参阅这个答案

在我的 docker 网络中能够通过这样做成功配置动态proxy_pass

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

请注意,它是添加 $uri$is_args$args 的基础,否则代理传递不会考虑路径和查询 细绳。

PS:在我的示例中,我正在使用 $http_XBackend 变量读取标头。标头由客户端以 XBackend: host 形式传递,这里的 host 应该是您要将呼叫转发到的主机名。我尝试使用带有破折号的标题,但没有成功,我不得不使用不带破折号的标题。


2020 年 7 月 16 日编辑:Docker 不再在其网页上报告默认 DNS 服务器的地址。仍然是 127.0.0.11:53。如果您想在容器内查看此值,您需要运行 cat /etc/resolv.conf 。

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 query string.

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.


Edit 16 Jul 2020: Docker doesn't report any more on their webpage the address for the default DNS server. It is still 127.0.0.11:53. If you want to see this value inside your container you need to run cat /etc/resolv.conf.

染墨丶若流云 2024-11-09 20:10:51

偶然发现同样的问题

proxy_pass 无法解析我的变量,直到我们发现我们的 DNS 服务器有问题,

可以用这个 cmd 顺便检查一下

nslookup your-domain your-dns-ip

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
三生一梦 2024-11-09 20:10:51
 location / {
   if ($args ~ "^url=(.+)") { #gets the "url" get parameter
       set $key1 $1;
     proxy_pass $key1;#use the parameter as proxy address
 }
}
 location / {
   if ($args ~ "^url=(.+)") { #gets the "url" get parameter
       set $key1 $1;
     proxy_pass $key1;#use the parameter as proxy address
 }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文