Nginx proxy_pass仅部分起作用 [英] Nginx proxy_pass only works partially
问题描述
我有以下设置
- 主服务器-称为
https://master.com
- 从服务器-称为
https://slave.com
- Master server - call it
https://master.com
- Slave server - call it
https://slave.com
两者都在Ubuntu 16.04上运行Nginx
Both run Nginx on Ubuntu 16.04
在主服务器上,我已经在/etc/nginx/sites-available/default
文件中创建了以下配置块
On the master server I have created the following configuration block in my /etc/nginx/sites-available/default
file
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
上的service nginx reload
,我可以执行以下操作
A service nginx reload
later on master.com
and I can do the following
- 浏览到
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
中的图像.
- Browse to
https://master.com/test
and view the output fromslave.com\index.php
. - Browse to
https://master.com/test/test.txt
and see the text in the fileslave.com\test.txt
- Browse to
https://master/com/test/test.jpg
and see the image in the fileslave.com\test.jpg
.
但是,我不能执行以下任何操作
However, I cannot do any of the following
- 浏览到
https://master.com/test/test.php
,而不是显示https://slave.com/test.php
的输出,而是显示404错误消息 - 浏览到
https://master.com/test/adminer/adminer.php
,而不是向我显示从服务器上Adminer实例的登录屏幕,而https://slave.com/adminer/adminer.php
向我显示master.com
上Adminer实例的登录屏幕.https://master.com/adminer/adminer.php
- Browse to
https://master.com/test/test.php
which instead of showing me the output fromhttps://slave.com/test.php
shows me a 404 error message - Browse to
https://master.com/test/adminer/adminer.php
which instead of showing me the login screen for the Adminer instance on the slave,https://slave.com/adminer/adminer.php
shows me the login screen for the Adminer instance onmaster.com
i.e.https://master.com/adminer/adminer.php
这显然是因为我在master.com
的Nginx配置中缺少某些内容.但是,我看不出那是什么.
This is clearly because I am missing something in my Nginx configuration on master.com
. However, I am unable to see what that might be.
为了完整性,这是我在两台服务器上的配置:
In the interests of completeness, here is my configuration on both servers:
Ubuntu -16.04.3 Nginx -1.10.3 PHP -7.0.22
Ubuntu - 16.04.3 Nginx - 1.10.3 PHP - 7.0.22
我应该解释为什么需要^~
,因为从我的原始问题尚不清楚.我还有另一个块设置来处理master.com
上的PHP脚本.
I should explain why the ^~
is required since this is not clear from my original question. I have another block setup to handle PHP scripts on master.com
.
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
脚本.避免这种情况的唯一方法是使用^~
Because of the way Nginx processes these directives this block takes priority when it comes to handling .php
files and master.com
ends up looking locally for .php
scripts that are actually on slave.com
. The only way to avoid this is to use ^~
推荐答案
您的方法是错误的.在处理/test
的块内,将其重写并发送到该块之外.实际上,proxy_pass
永远不会发生,因为新URL中没有/test
.解决方案很简单,不要使用重写
Your approach is wrong. Inside the block which handles /test
your rewrite it and send it out of the block. The proxy_pass
never actually happens because the new URL doesn't have /test
in it. Solution is simple, don't use 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
地址
Appending /
at the end of the location path and also the proxy_pass
server will make sure what is after /test/
is sent to your proxy_pass
address
编辑1
这是我在发布此答案之前设置的示例测试用例.
Here is a sample test case I had set before posting this answer.
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个位置块之间的区别
Now the results explains the difference between all 4 location blocks
$ 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
网址中看到的那样,代理服务器仅看到/abc/test
As you can see in /test4
url the proxied server only sees /abc/test
这篇关于Nginx proxy_pass仅部分起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!