Nginx proxy_pass仅部分起作用

Nginx proxy_pass仅部分起作用,nginx,reverse-proxy,php-7,Nginx,Reverse Proxy,Php 7,我有以下设置 主服务器-称之为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;

我有以下设置

  • 主服务器-称之为
    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.com上重新加载
服务nginx
,我可以执行以下操作

  • 浏览至
    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.php
    它没有显示从机上管理员实例的登录屏幕,
    https://slave.com/adminer/adminer.php
    显示
    master.com上管理员实例的登录屏幕
    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
脚本。避免这种情况的唯一方法是使用
^ ~

您的方法是错误的。在处理
/test
的块内,重写并将其发送出块。由于新URL中没有
/test
,因此
代理过程实际上从未发生过。解决方案很简单,不要使用重写

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;
}
/
添加到位置路径的末尾以及
代理通行证
服务器将确保将
/test/
发送到您的
代理通行证
地址后的内容

编辑-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
上终止斜杠。然而,这并不是完全正确的答案。由于在目标服务器上请求的资源位于文档根目录中,而不是子文件夹
/test
中,因此需要进行
重写。我记得我不久前遇到过这个问题,并且得到了[从@Serioudron开始这样做。要长话短说,
位置/test/
需要改为
位置^~/test/
,一切都正常!@DroidOS,答案是正确的,您不需要重写。如果由于优先级顺序,有另一个位置正在处理您的请求,您需要
^~
。因此,如果您检查我的编辑,您将看到为什么以及何时不需要重写