proxy_recirect
修改URI
原文:http://www.aslibra.com/blog/post/nginx_proxy_redirect.php
Nginx的代理功能太完善了,我们看看proxy_redirect参数的作用。
案例说明
要做一个html.aslibra.com的域名处理很多网站的html内容,当然是后端的服务器了,目录区分:
html.zcom.com/img.aslibra.com/ html.zcom.com/css.aslibra.com/
访问的域名是该目录下的域名,那前端nginx的配置应该类似这样:
server { server_name img.aslibra.com; location / { rewrite ^(.*) /$http_host$1 break; proxy_set_header Host html.aslibra.com; proxy_pass http://cache-89; } }
但这样访问目录时如果没有以“/”结尾,则服务器会返回301redirect:
curl -I http://img.aslibra.com/www HTTP/1.1 301 Moved Permanently Server: nginx/0.7.59 Date: Tue, 21 Jul 2009 15:28:58 GMT Connection: keep-alive Location: http://html.aslibra.com/img.aslibra.com/www/
html.aslibra.com这个域名并非公布的域名,返回给客户端是会自然产生错误的Nginx可以很好的处理这个问题:
server { server_name img.aslibra.com; location / { rewrite ^(.*) /$http_host$1 break; proxy_set_header Host html.aslibra.com; proxy_pass http://cache-89; proxy_redirect http://html.aslibra.com/img.aslibra.com/ /; } }
加一行proxy_redirect后,正常了:
curl -I http://img.aslibra.com/www HTTP/1.1 301 Moved Permanently Server: nginx/0.7.59 Date: Tue, 21 Jul 2009 15:23:49 GMT Content-Type: text/html Location: http://img.aslibra.com/www/ Connection: keep-alive Content-Length: 185 Expires: Tue, 21 Jul 2009 16:23:49 GMT Cache-Control: max-age=3600
就这么样就ok啦~
不过貌似不支持变量出现在地址里,这个就郁闷了,必须指定相应域名。
对于多个域名匹配的server,redirect设置不能写作'/'了,否则会用第一个域名作为redirect域名
可以写几个匹配规则:
proxy_redirect http://html.aslibra.com/img.aslibra.com/ http://img.aslibra.com/; proxy_redirect http://html.aslibra.com/css.aslibra.com/ http://css.aslibra.com/;
修改端口
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; } }
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 / /;
Nginx像Apache一样做反向代理
我们都知道Nginx是可以做反向代理的,就像Apache的ProxyPassReverse一样。 在apache中配置反向代理,我们这样写:
<VirtualHost myhost:80> ServerName myhost DocumentRoot /path/to/myapp/public ProxyPass / http://myapp:8080/ ProxyPassReverse / http://myapp:8080/ </VirtualHost>
但是Nginx没有ProxyPassReverse,解决办法就是添加丢失的HTTP头:
server { listen myhost:80; server_name myhost; location / { root /path/to/myapp/public; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://myapp:8080; } }
那些丢失的头信息都是什么呢?
X-Forwarded-For:客户端IP地址 X-Forwarded-Host:客户端发起的原始主机请求头信息 X-Forwarded-Server:代理服务器主机名