前言
nginx有時候并不像apache那樣智能,對于redirect location的處理尤為慘淡,幾乎只能用戶手工處理非標準端口的問題。
比如因為種種原因,nginx并不能監(jiān)聽在80端口,或者外部通過NAT方式將請求丟給nginx,外部地址并不是標準http(s)端口,此時nginx并不能美好的處理這些重定向。發(fā)生重定向的時候會丟失端口。
比如以下兩種參考范例:
#反向代理
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的時候,瀏覽器發(fā)出請求`http://xxx.com/data`
# 未查詢到/data文件,url被重定向到`http://xxx.com/data/`目錄
listen 81 default_server;
location /data {
root /var/data;
}
瀏覽器請求的時候會發(fā)現(xiàn)只要發(fā)生重定向,端口號就會丟失,導(dǎo)致瀏覽器訪問到錯誤的端口。
分別對這兩種情況給出解決方案。
反向代理
這個很容易搞定,那一堆proxy_set_header不知道何時在網(wǎng)上流傳開來的,幾乎國內(nèi)外文檔無一例外都是這個鳥樣子。后來我發(fā)現(xiàn)gitlab-ce這個用非標準端口訪問是沒有問題的,我看了一下gitlab-ce的nginx配置,發(fā)現(xiàn)是這么配置的:
proxy_set_header Host $http_host;
我又發(fā)現(xiàn)nginx軟件包釋放出的配置文件,發(fā)現(xiàn)里面其實是帶有一個參考文件/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;
}
沒這個文件就把這些內(nèi)容手工敲到location配置段下。
再細看官方文檔,其實也提及了:
An unchanged “Host” request header field can be passed like this:
proxy_set_header Host $http_host;
訪問目錄沒帶/
這個比較棘手,比如$document_root存在data/index.html文件,但是訪問的時候使用的是/data最后沒加/去表示其訪問的是一個目錄,服務(wù)器此時會進行301 Moved Permanently永久重定向處理,但是比較扯的地方在于,如果nginx監(jiān)聽的是非標準端口,這個301返回的Location沒有端口號,導(dǎo)致瀏覽器請求出錯。
用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重寫的形式帶上端口號,問題解決。
轉(zhuǎn)載自:http://www.voidcn.com/article/p-nocikewh-bpa.html