nginx处理redirect location端口丢失的问题
博客专区 > Feng_Yu 的博客 > 博客详情
nginx处理redirect location端口丢失的问题
Feng_Yu 发表于2年前
nginx处理redirect location端口丢失的问题
  • 发表于 2年前
  • 阅读 1147
  • 收藏 6
  • 点赞 1
  • 评论 1
摘要: nginx有时候并不像apache那样智能,对于redirect location的处理尤为惨淡,几乎只能用户手工处理

前言

nginx有时候并不像apache那样智能,对于redirect location的处理尤为惨淡,几乎只能用户手工处理非标准端口的问题。

比如因为种种原因,nginx并不能监听在80端口,或者外部通过NAT方式将请求丢给nginx,外部地址并不是标准http(s)端口,此时nginx并不能美好的处理这些重定向。发生重定向的时候会丢失端口。

比如以下两种参考范例:

#反向代理
    listen 81 default_server;
    set $TOMCAT_HOME /var/lib/tomcat7;

    location / {
		root $TOMCAT_HOME/webapps/ROOT;
		proxy_pass http://127.0.0.1:8080/;
		proxy_set_header Host             $host;
		proxy_set_header X-Real-IP        $remote_addr;  
		proxy_set_header X-Forwarded-For  $proxy_add_x_forwarded_for;
	}

# 访问/data的时候会自动加上/成为/data/
listen 81 default_server;

location /data {
    root /var/data;
}

浏览器请求的时候会发现只要发生重定向,端口号就会丢失,导致浏览器访问到错误的端口。

分别对这两种情况给出解决方案。

反向代理

这个很容易搞定,那一堆proxy_set_header不知道何时在网上流传开来的,几乎国内外文档无一例外都是这个鸟样子。后来我发现gitlab-ce这个用非标准端口访问是没有问题的,我看了一下gitlab-ce的nginx配置,发现是这么配置的:

proxy_set_header Host             $http_host;

我又发现nginx软件包释放出的配置文件(from ppa: NGINX Stable),发现里面其实是带有一个参考文件/etc/nginx/proxy_params

proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

这里面写的也是 proxy_set_header Host $http_host;,于是乎直接include,搞定

    location / {
		root $TOMCAT_HOME/webapps/ROOT;
		proxy_pass http://127.0.0.1:8080/;
		include proxy_params;
	}

没这个文件就把这些内容手工敲到location配置段下。

再细看官方文档,其实也提及了:

An unchanged “Host” request header field can be passed like this:

    proxy_set_header Host       $http_host;

访问目录没带/

这个比较棘手,比如$document_root存在data/index.html文件,但是访问的时候最后没加/,nginx会自动给你带上/,返回一个301重定向(这个行为和apache一致),但是比较扯的地方在于,如果nginx监听的是非标准端口,这个301返回的Location没有端口号,导致浏览器请求出错。用curl可以很明显的看到这一点:

$ curl -v mydomain:81/data
* Hostname was NOT found in DNS cache
*   Trying *.*.*.*...
* Connected to mydomain (*.*.*.*) port 81 (#0)
> GET /test HTTP/1.1
> User-Agent: curl/7.35.0
> Host: mydomain:81
> Accept: */*
> 
< HTTP/1.1 301 Moved Permanently
* Server nginx is not blacklisted
< Server: nginx
< Date: Wed, 18 Nov 2015 07:39:03 GMT
< Content-Type: text/html
< Content-Length: 178
< Connection: keep-alive
< Location: http://mydomain/data/
< 
<html>
<head><title>301 Moved Permanently</title></head>
<body bgcolor="white">
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx</center>
</body>
</html>
* Connection #0 to host mydomain left intact

可以很明显的看到Location没有端口号了,这个重定向又和反向代理不一样。于是遍寻google,最终在stackoverflow的问答中找到了解决方案:

        if (-d $request_filename) {
            rewrite [^/]$ $scheme://$http_host$uri/ permanent;
        }

通过手工对URL重写的形式带上端口。

标签: nginx
共有 人打赏支持
粉丝 146
博文 38
码字总数 45477
评论 (1)
×
Feng_Yu
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: