【问题标题】:Nginx proxy_pass only works partiallyNginx proxy_pass 只能部分工作
【发布时间】:2018-02-19 14:51:13
【问题描述】:

我有以下设置

  • 主服务器 - 称它为https://master.com
  • 从服务器 - 称它为https://slave.com

两者都在 Ubuntu 16.04 上运行 Nginx

在主服务器上,我在 /etc/nginx/sites-available/default 文件中创建了以下配置块

location /test
{
 rewrite ^/test(.*) /$1 break;
 proxy_pass https://slave.com;
 proxy_read_timeout 240;
 proxy_redirect off;
 proxy_buffering off;
 proxy_set_header Host $host;
 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 proxy_set_header X-Forwarded-Proto https;
}

稍后master.comservice nginx reload 我可以执行以下操作

  • 浏览到https://master.com/test 并查看slave.com\index.php 的输出。
  • 浏览到https://master.com/test/test.txt并查看文件slave.com\test.txt中的文本
  • 浏览到https://master/com/test/test.jpg 并查看文件slave.com\test.jpg 中的图像。

但是,我无法执行以下任何操作

  • 浏览到 https://master.com/test/test.php,而不是向我显示来自 https://slave.com/test.php 的输出,而是向我显示 404 错误消息
  • 浏览到https://master.com/test/adminer/adminer.phphttps://slave.com/adminer/adminer.php向我显示了master.comi.e 上Adminer 实例的登录屏幕,而不是向我显示从属服务器上的Adminer 实例的登录屏幕。 https://master.com/adminer/adminer.php

这显然是因为我在master.com 上的 Nginx 配置中遗漏了一些东西。但是,我看不出那可能是什么。

为了完整起见,这是我在两台服务器上的配置:

Ubuntu - 16.04.3 Nginx - 1.10.3 PHP - 7.0.22

我应该解释为什么需要^~,因为这在我最初的问题中并不清楚。我有另一个块设置来处理master.com 上的 PHP 脚本。

location ~ \.php$ 
{
 try_files $uri =404;
 fastcgi_split_path_info ^(.+\.php)(/.+)$;
 fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
 fastcgi_index index.php;
 fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
 include fastcgi_params;
}

由于 Nginx 处理这些指令的方式,该块在处理 .php 文件时具有优先权,而 master.com 最终会在本地查找实际上位于 slave.com 上的 .php 脚本。避免这种情况的唯一方法是使用^~

【问题讨论】:

    标签: nginx reverse-proxy php-7


    【解决方案1】:

    你的方法是错误的。在处理/test 的块内重写它并将其发送到块外。 proxy_pass 从未真正发生过,因为新 URL 中没有 /test。解决方法很简单,不要用rewrite

    location /test/
    {
     proxy_pass https://slave.com/;
     proxy_read_timeout 240;
     proxy_redirect off;
     proxy_buffering off;
     proxy_set_header Host $host;
     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
     proxy_set_header X-Forwarded-Proto https;
    }
    

    在位置路径的末尾附加/ 以及proxy_pass 服务器将确保将/test/ 之后的内容发送到您的proxy_pass 地址

    Edit-1

    这是我在发布此答案之前设置的示例测试用例。

    events {
        worker_connections  1024;
    }
    http {
    server {
       listen 80;
    
       location /test1 {
         proxy_pass http://127.0.0.1:81;
       }
    
       location /test2 {
         proxy_pass http://127.0.0.1:81/;
       }
    
       location /test3/ {
         proxy_pass http://127.0.0.1:81;
       }
    
       location /test4/ {
         proxy_pass http://127.0.0.1:81/;
       }
    
    }
    
    server {
       listen 81;
    
       location / {
         echo "$request_uri";
       }
    }
    }
    

    现在结果解释了所有 4 个位置块之间的差异

    $ curl http://192.168.33.100/test1/abc/test
    /test1/abc/test
    
    $ curl http://192.168.33.100/test2/abc/test
    //abc/test
    
    $ curl http://192.168.33.100/test3/abc/test
    /test3/abc/test
    
    $ curl http://192.168.33.100/test4/abc/test
    /abc/test
    

    正如您在/test4 url 中看到的那样,代理服务器只能看到/abc/test

    【讨论】:

    • 我赞成您的回答,因为您正确地提到我需要 /test 上的 /terminating 斜线。然而,这并不是完全正确的答案。 rewrite 是必需的,因为在目标服务器上,请求的资源位于文档根目录中,而不是在子文件夹 /test 中。我记得我不久前遇到过这个问题,并且从@SeriousDron 那里得到了 [stackoverflow.com/questions/29212655/… 在 SO 上。长话短说location /test/需要改为阅读location ^~/test/,一切正常!
    • @DroidOS,答案是正确的,你不需要重写。如果由于优先顺序而有另一个位置正在处理您的请求,您将需要^~。因此,如果您检查我的编辑,您将了解为什么以及何时不需要重写
    猜你喜欢
    • 2017-10-29
    • 1970-01-01
    • 2014-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-18
    • 2021-07-18
    • 2014-07-27
    相关资源
    最近更新 更多