如何使用 nginx proxy_pass 保留请求 url

Posted

技术标签:

【中文标题】如何使用 nginx proxy_pass 保留请求 url【英文标题】:How to preserve request url with nginx proxy_pass 【发布时间】:2011-08-15 14:18:55 【问题描述】:

我在尝试使用 Thin 应用服务器时遇到了一个问题。

nginx proxies 使用 proxy_pass http://my_app_upstream; 对 Thin(或 Unicorn)的请求时,应用程序会收到 nginx 发送的修改后的 URL(http://my_app_upstream)。

我想要的是传递原始 URL 和来自客户端的原始请求而不进行任何修改,因为应用程序严重依赖它。

nginx'doc 说:

如果需要在 未处理的表格 then 指令 proxy_pass 应该在没有 URI 的情况下使用 部分。

但我不明白如何准确配置它,因为相关示例实际上使用的是 URI:

location  /some/path/ 
  proxy_pass   http://127.0.0.1;

那么请您帮我弄清楚如何保留来自客户端的原始请求 URL

【问题讨论】:

【参考方案1】:

我认为proxy_set_header 指令会有所帮助:

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

【讨论】:

请注意其他人发现这一点:使 nginx 不操纵 URL 的解决方案的核心是删除 proxy_pass 指令末尾的斜杠。 http://my_app_upstreamhttp://my_app_upstream/ 对我来说,发生的事情是当 JSP 进行重定向时,my_app_upstream 主机名出现了。使用proxy_set_header Host $host 修改并使Tomcat/JSP 认为它是一个实际的客户端请求域。感谢您的帮助 @HugoJosefson 哇,感谢上帝,我注意到了你的帖子。这应该在答案中明确 就我而言,@HugoJosefson 的解决方案不起作用。我指的是localhost:port;我必须设置标题。 这是一个改进,但没有保留方案(http 或 https)。现在我的https://example.com/page uris 变成了http://example.com/page【参考方案2】:

其他发现此问题的人的注意事项:解决方案的核心 nginx不是操纵网址,就是去掉末尾的斜杠 复制:proxy_pass 指令。 http://my_app_upstream 与 http://my_app_upstream/ – 雨果约瑟夫森

我在上面的 cmets 中找到了这个,但我认为它确实应该是一个答案。

【讨论】:

【参考方案3】:

nginx 还提供了 $http_host 变量,它将为您传递端口。 它是主机和端口的串联。

所以你只需要这样做:

proxy_set_header Host $http_host;

【讨论】:

【参考方案4】:

对于我的身份验证服务器...这有效。我喜欢为我自己的人性化可读性提供 /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;
      

在conf的底部

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

【讨论】:

【参考方案5】:

如果某些东西修改了您尝试服务的位置,例如try_files,这样就保留了对后端的请求:

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

【讨论】:

【参考方案6】:

在我的场景中,我通过 nginx vhost 配置中的以下代码实现了这一点

server 
server_name dashboards.etilize.com;

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

$http_host 将在 Header 中设置与请求相同的 URL

【讨论】:

【参考方案7】:

在不切断请求的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;
    

在这里找到:https://opensysnotes.wordpress.com/2016/11/17/nginx-proxy_pass-with-absolute-url/

【讨论】:

【参考方案8】:

只是 proxy_set_header 主机 $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;

【讨论】:

谢谢,这是我缺少的部分($server_port),用于在代理后面的端点上进行 OAuth 验证。 我在 sinatra 中使用机架保护,并且在 POST URL 上被禁止。将端口添加到主机代理标头为我修复了它。 这在最新版本的 Nginx 中不再起作用我认为***.com/questions/31482796/…

以上是关于如何使用 nginx proxy_pass 保留请求 url的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 nginx 通过 proxy_pass 转发查询字符串参数?

如何解决 Nginx “proxy_pass 502 Bad Gateway”错误

转:NGINX中的proxy_pass和rewrite

如何更改 nginx proxy_pass 中的 request_uri?

nginx proxy_pass基于请求方法是POST,PUT还是DELETE

Nginx Proxy_pass简述