NGINX中proxy_redirect的作用
NGINX的proxy_redirect功能比较强大,其作用是对发送给客户端的URL进行修改。以例子说明:
例一:
server {
listen 80;
server_name test.abc.com;
location / {
proxy_pass http://10.10.10.1:9080;
}
}
这段配置一般情况下都正常,但偶尔会出错, 错误在什么地方呢?
抓包发现服务器给客户端的跳转指令里加了端口号,如 Location: http://test.abc.com:9080/abc.html
。因为nginx服务器侦听的是80端口,所以这样的URL给了客户端,必然会出错.针对这种情况, 加一条proxy_redirect指令: proxy_redirect http://test.abc.com:9080/ /
,把所有http://test.abc.com:9080/
的内容替换成/
再发给客户端,就解决了。
server {
listen 80;
server_name test.abc.com;
proxy_redirect http://test.abc.com:9080/ /;
location / {
proxy_pass http://10.10.10.1:9080;
}
}
例二:
下面这段环境是这样,浏览器访问https://account.abc.com/
会转至后端的http://proxy/account/
上。是通过rewrite做的。
server {
listen 443;
server_name account.abc.com;
ssl on;
ssl_certificate abc.com.pem;
ssl_certificate_key abc.com.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
root /data1/www/;
index index.php index.html index.htm;
access_log /data1/log/nginx/account.abc.com-https.log main;
error_log /data1/log/nginx/account.abc.com-https-error.log warn;
rewrite ^/(.*)$ /account/$1 last;
location /account {
proxy_pass http://account;
proxy_cookie_path /account/ /;
}
}
没有特殊情况,这么做一直是OK的。
但是当后端的服务器需要做一个302跳转时,问题就出来了。会跳转到类似的URL:
http://account.abc.com/account/xxxx
而我们希望的跳转URL其实是:
https://account.abc.com/xxxx
解决办法是使用proxy_redirect改写返回到浏览器的URL:
server {
listen 443;
server_name account.abc.com;
ssl on;
ssl_certificate abc.com.pem;
ssl_certificate_key abc.com.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
root /data1/www/;
index index.php index.html index.htm;
access_log /data1/log/nginx/account.abc.com-https.log main;
error_log /data1/log/nginx/account.abc.com-https-error.log warn;
rewrite ^/(.*)$ /account/$1 last;
location /account {
proxy_pass http://account;
proxy_cookie_path /account/ /;
proxy_redirect http://account.abc.com/account $scheme://account.abc.com;
}
}
proxy_redirect官方说明
语法:proxy_redirect [ default|off|redirect replacement ]
默认值:proxy_redirect default
使用字段:http, server, location
如果需要修改从被代理服务器传来的应答头中的”Location”和”Refresh”字段,可以用这个指令设置。
假设被代理服务器返回Location字段为: http://localhost:8000/two/some/uri/
这个指令:
proxy_redirect http://localhost:8000/two/ http://frontend/one/;
将Location字段重写为http://frontend/one/some/uri/。
在代替的字段中可以不写服务器名:
proxy_redirect http://localhost:8000/two/ /;
这样就使用服务器的基本名称和端口,即使它来自非80端口。
如果使用“default”参数,将根据location和proxy_pass参数的设置来决定。
例如下列两个配置等效:
location /one/ {
proxy_pass http://upstream:port/two/;
proxy_redirect default;
}
location /one/ {
proxy_pass http://upstream:port/two/;
proxy_redirect http://upstream:port/two/ /one/;
}
在指令中可以使用一些变量:
proxy_redirect http://localhost:8000/ http://$host:$server_port/;
这个指令有时可以重复:
proxy_redirect default;
proxy_redirect http://localhost:8000/ /;
proxy_redirect http://www.example.com/ /;
参数off将在这个字段中禁止所有的proxy_redirect指令:
proxy_redirect off;
proxy_redirect default;
proxy_redirect http://localhost:8000/ /;
proxy_redirect http://www.example.com/ /;
利用这个指令可以为被代理服务器发出的相对重定向增加主机名:
proxy_redirect / /;