如何在使用nginx的proxy_pass时保留请求的url

109
我正在尝试使用Thin应用服务器,但遇到了一个问题。
当nginx proxies请求到Thin(或Unicorn)时,使用proxy_pass http://my_app_upstream;,应用程序会接收到由nginx发送的修改后的URL(http://my_app_upstream)。
我想传递原始URL和原始客户端请求,而不进行任何修改,因为该应用程序在很大程度上依赖于它。
nginx的doc如下所示:

如果有必要以未处理的形式传输URI,则应使用不带URI部分的指令proxy_pass。

但我不明白如何配置它,因为相关示例实际上正在使用URI。
location  /some/path/ {
  proxy_pass   http://127.0.0.1;
}

那么,您能帮我找出如何从客户端保留原始请求URL吗?


"Thin"现在指向404。 - Alexis Tyler
8个回答

175

我认为 proxy_set_header 指令可以帮助:

location / {
    proxy_pass http://my_app_upstream;
    proxy_set_header Host $host;
    # ...
}

135
其他人请注意:解决让nginx不操作URL的关键是删除proxy_pass指令末尾的斜杠。例如,http://my_app_upstreamhttp://my_app_upstream/是不同的。 - Hugo Josefson
2
对我来说,发生的情况是当JSP进行重定向时,my_app_upstream主机名会显示出来。使用“proxy_set_header Host $host”进行修改,使Tomcat/JSP认为它是实际客户端请求的域名。感谢您的帮助。 - ankitjaininfo
1
@HugoJosefson 哇,感谢上帝我注意到了你的帖子。这应该在答案中明确说明。 - plus-
3
在我的情况下,@HugoJosefson的解决方案行不通。我当时指向的是http://localhost:port;我必须设置头文件。 - user1316498
2
这是一个改进,但是方案(http或https)没有被保留。现在我的 https://example.com/page URI 变成了 http://example.com/page - John Smith Optional
显示剩余2条评论

13

对于我的情况,只是 proxy_set_header Host $host 缺少端口。 解决方法是:



    location / {
     proxy_pass http://BACKENDIP/;
     include /etc/nginx/proxy.conf;
    }

然后在proxy.conf文件中



    proxy_redirect off;
    proxy_set_header Host $host:$server_port;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;


2
谢谢,这正是我缺少的部分($server_port),以便在代理后面的端点上使OAuth验证工作。 - renier
我正在使用sinatra和rack-protection,但在POST URL上遇到了Forbidden的问题。将端口添加到代理头中的主机解决了我的问题。 - pduey
1
这在最新版本的Nginx中不再起作用了。我认为你可以参考这个链接:https://dev59.com/2FwZ5IYBdhLWcg3waft6?s=1|3.2072 - iwein

10
nginx还提供了$http_host变量,它将为您传递端口。它是主机和端口的拼接。
因此,您只需要执行以下操作:
proxy_set_header Host $http_host;

9

如果有什么修改正在尝试提供的位置,例如try_files,则会保留向后端的请求:

location / {
  proxy_pass http://127.0.0.1:8080$request_uri;
}

8

3
为了完美转发请求中的absoluteURI和头部中的Host而不切割它们:
server {
    listen 35005;

    location / {
        rewrite            ^(.*)$   "://$http_host$uri$is_args$args";
        rewrite            ^(.*)$   "http$uri$is_args$args" break;
        proxy_set_header   Host     $host;

        proxy_pass         https://deploy.org.local:35005;
    }
}

这里找到了一个关于使用绝对URL的Nginx proxy_pass的教程:https://opensysnotes.wordpress.com/2016/11/17/nginx-proxy_pass-with-absolute-url/


2
在我的场景中,我通过以下代码在nginx虚拟主机配置中实现了这一点。
server {
server_name dashboards.etilize.com;

location / {
    proxy_pass http://demo.etilize.com/dashboards/;
    proxy_set_header Host $http_host;
}}

$http_host将设置与请求相同的标头URL


-1

对于我的认证服务器...这个可以工作。我喜欢为我的/auth拥有选项,以便更容易阅读...或者我也可以通过端口/上游配置它,用于机器之间的通信。

.

在 conf 开始处

####################################################
upstream auth {
    server 127.0.0.1:9011 weight=1 fail_timeout=300s;
    keepalive 16;
  }

在我的443服务器块内部

          if (-d $request_filename) {
          rewrite [^/]$ $scheme://$http_host$uri/ permanent;
      }

  location /auth {
          proxy_pass http://$http_host:9011;
          proxy_set_header Origin           http://$host;
          proxy_set_header Host             $http_host:9011;
          proxy_set_header X-Forwarded-For  $proxy_add_x_forwarded_for;
          proxy_set_header Upgrade          $http_upgrade;
          proxy_set_header Connection       $http_connection;
          proxy_http_version 1.1;
      }

在配置文件底部

#####################################################################
#                                                                   #
#     Proxies for all the Other servers on other ports upstream     #
#                                                                   #
#####################################################################


#######################
#        Fusion       #
#######################

server {
    listen 9001 ssl;

#############  Lock it down  ################

# SSL certificate locations
    ssl_certificate /etc/letsencrypt/live/allineed.app/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/allineed.app/privkey.pem;

# Exclusions

    include snippets/exclusions.conf;

# Security

    include snippets/security.conf;
    include snippets/ssl.conf;

# Fastcgi cache rules

    include snippets/fastcgi-cache.conf;
    include snippets/limits.conf;
    include snippets/nginx-cloudflare.conf;

###########  Location upstream ##############

    location  ~ / {
        proxy_pass http://auth;
        proxy_set_header Origin           http://$host;
        proxy_set_header Host             $host:$server_port;
        proxy_set_header X-Forwarded-For  $proxy_add_x_forwarded_for;
        proxy_set_header Upgrade          $http_upgrade;
        proxy_set_header Connection       $http_connection;
        proxy_http_version 1.1;
    }
        if (-d $request_filename) {
        rewrite [^/]$ $scheme://$http_host$uri/ permanent;
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接