成功最有效的方法就是向有经验的人学习!

Nginx之proxy_redirect详解

今天在做nginx反向代理apache的时候出了一点点问题,原来后端apache用的端口是8080通过反向代理后,使用wireshark抓包发现location头域数值为http://192.168.1.154:8080/wuman/如果把这个返回给客户端肯定是不可以的,看起来别扭而且还暴露了apache的具体信息

所以在这里用到了nginx的proxy_redirect指定修改被代理服务器返回的响应头中的location头域跟refresh头域数值

以下是截取nginx的一小段配置文档

server {
listen 80;
server_name www.boke.com;
location / {
proxy_pass http://192.168.1.154:8080;
proxy_redirect off;
}
}

此时我们通过curl查看结果得出

[root@localhost nginx]# curl -I http://www.boke.com/wuman
HTTP/1.1 301 Moved Permanently
Server: nginx
Date: Thu, 24 Dec 2015 12:02:00 GMT
Content-Type: text/html; charset=iso-8859-1
Connection: keep-alive
Location: http://192.168.1.154:8080/wuman/

这里location为带有后端服务器实际地址跟端口的响应头信息这样在实际线上是不允许的所以这里我们打算通过proxy_redirect将被代理服务器的响应头中的location字段进行修改后返回给客户端

server {
listen 80;
server_name www.boke.com;
location / {
proxy_pass http://192.168.1.154:8080;
proxy_redirect http://192.168.1.154:8080/wuman/ http://www.boke.com/wuman/;
}</pre>
<pre class="EnlighterJSRAW" data-enlighter-language="shell">server {
listen 80;
server_name www.boke.com;
location / {
proxy_pass http://192.168.1.154:8080;
proxy_redirect ~^http://192.168.1.154:8080(.*) http://www.boke.com$1;
}

则curl查看返回结果

[root@localhost nginx]# curl -I http://www.boke.com/wuman
HTTP/1.1 301 Moved Permanently
Server: nginx
Date: Thu, 24 Dec 2015 12:08:34 GMT
Content-Type: text/html; charset=iso-8859-1
Connection: keep-alive
Location: http://www.boke.com/wuman/

此时查看location已经变成了我们想要的结果了。 此时通过replacement 301重定向到了我们新的页面

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:代理服务器主机名
赞(0) 打赏
未经允许不得转载:陈桂林博客 » Nginx之proxy_redirect详解

大佬们的评论 2

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
  1. #2

    “`
    [root@localhost nginx]# curl -I http://www.boke.com/wuman
    HTTP/1.1 301 Moved Permanently
    Server: nginx
    Date: Thu, 24 Dec 2015 12:08:34 GMT
    Content-Type: text/html; charset=iso-8859-1
    Connection: keep-alive
    Location: http://www.boke.com/wuman/
    “`

    admin4年前 (2018-09-20)回复
  2. #1

    `hello`

    admin4年前 (2018-09-20)回复

全新“一站式”建站,高质量、高售后的一条龙服务

橙子建站.极速智能建站8折购买虚拟主机

觉得文章有用就打赏一下文章作者

非常感谢你的打赏,我们将继续给力更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫打赏

微信扫一扫打赏