當使用了Nginx代理,會出現Java用HttpServletRequest
的getServerName()
方法獲取不到域名,而是127.0.0.1的情況
復現
首先修改本地的hosts文件來模擬域名訪問
將test.com
添加到配置中
然后寫一個接口來輸出getServerName()
方法
@RequestMapping("/url")
public String url(HttpServletRequest request) {
System.out.println(request.getScheme());
System.out.println(request.getServerName());
System.out.println(request.getContextPath());
return request.getScheme() + "://" + request.getServerName() + request.getContextPath();
}
訪問http://test.com:8002/url
后看到接口返回http://test.com
隨后開啟一個Nginx,並配置好接口的代理
location ~ /url {
proxy_pass http://127.0.0.1:8002;
}
隨后通過Nginx去訪問接口http://test.com/url
會發現返回的結果是http://127.0.0.1
原因
問題的原因是經過Nginx后,沒有把http請求里的host轉發過來,獲取到的是Nginx的ip
location ~ /url {
#轉發host信息
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:8002;
}
通過這一行參數可以將host里的信息也轉發過來,作用是把原http請求的header中的host字段也放到轉發的請求
重新訪問后可以發現返回的是域名了
命令的作用
proxy_set_header
允許重新定義或追加字段到請求頭,然后再轉發
值可以是文本、變量或者組合
當前配置如果沒有指定,會繼承上一個配置文件的設置
默認的設置是
proxy_set_header Host $proxy_host;
proxy_set_header Connection close;
$proxy_host
就是代理服務器的host,所有會看到上述127.0.0.1
的出現
官網中還給出了兩個變量$host
和$http_host
,關於這兩個參數的區別官網也中給出了解釋
如果不想改變請求頭中host的值,可以使用$http_host
但是如果客戶端請求頭沒有帶host參數的話,轉發就不會攜帶host
推薦是使用$host
變量,它的值等於host請求報頭字段中的服務器名,如果這個字段不存在,則等於主服務器名
也可以自定義一個host來轉發
#代理服務器host
proxy_set_header Host $proxy_host;
#客戶端請求host
proxy_set_header Host $host;
proxy_set_header Host $http_host;
#自定義
proxy_set_header Host abc.com;
官網地址:http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_set_header