Nginx 301跳转踩坑总结
有一天,公司的服務(wù)切換域名,禁用了http協(xié)議,只允許通過https協(xié)議訪問。這時(shí)出現(xiàn)了一個(gè)奇奇怪怪的問題,在瀏覽器地址欄敲入url訪問靜態(tài)資源目錄時(shí),發(fā)現(xiàn)默認(rèn)跳轉(zhuǎn)到了http協(xié)議的地址。網(wǎng)絡(luò)拓?fù)浣Y(jié)構(gòu)如下:
如上圖所示,客戶端https請(qǐng)求先到達(dá)API網(wǎng)關(guān),然后網(wǎng)關(guān)將請(qǐng)求通過http協(xié)議轉(zhuǎn)發(fā)到靜態(tài)資源服務(wù)器。
調(diào)出瀏覽器發(fā)現(xiàn)客戶端發(fā)送的https請(qǐng)求收到了一個(gè)301狀態(tài)碼的響應(yīng),并且響應(yīng)頭中的Location字段便是跳轉(zhuǎn)到的http協(xié)議的地址。
1.原因分析
為啥服務(wù)端會(huì)返回301呢?首先需要弄清楚狀態(tài)碼的含義。HTTP協(xié)議中3xx開頭的狀態(tài)響應(yīng)碼都是表示重定向的響應(yīng)。根據(jù)RFC的定義:
301 Moved Permanently
302 Found
303 See Other
307 Temporary Redirect
301是永久重定向。如果使用Nginx作為HTTP服務(wù)器,那么當(dāng)用戶輸入一個(gè)不存在的地址之后,基本上會(huì)有兩種情況:1.返回404狀態(tài)碼,2.返回301狀態(tài)碼和重定向地址。404 Not Found不做討論,只說下301 Moved Permanently的處理過程。
首先需要明確的問題是,301重定向在什么情況下會(huì)被觸發(fā)呢?
答案是:Nginx負(fù)責(zé)設(shè)置301 Moved Permanently狀態(tài)碼。但nginx.conf控制Nginx如何處理301 Moved Permanently狀態(tài)碼! 換句話說,要不要進(jìn)行頁(yè)面重定向,和怎么重定向,完全是用戶配置的結(jié)果! Nginx主動(dòng)設(shè)置301 Moved Permanently狀態(tài)碼只有一種情況,當(dāng)用戶在瀏覽器輸入了一個(gè)url地址,末尾部分是一個(gè)文件目錄且不以斜杠”/“結(jié)尾,比如 “www.test.com/index” 。 Nginx沒有找到index這個(gè)文件,但發(fā)現(xiàn)了index是個(gè)目錄。于是本次訪問的返回狀態(tài)碼就會(huì)被設(shè)置成301 Moved Permanently。
瀏覽器與Nginx的通信過程如下所示:
一般情況下,我們會(huì)在nginx.conf中配置absolute_redirect ,server_name_in_redirect和port_in_redirect,以便到達(dá)個(gè)性化的重定向功能。其中absolute_redirect控制Location url的生成方式。
- absolute_redirect設(shè)置成on,則生成絕對(duì)路徑作為L(zhǎng)ocation url。
- absolute_redirect設(shè)置成off,則生成相對(duì)路徑作為L(zhǎng)ocation url。
只有absolute_redirect設(shè)置為on時(shí),另外兩個(gè)配置才會(huì)生效。
- server_name_in_redirect為on時(shí),使用Nginx配置文件中的server_name作為L(zhǎng)ocation url中的host,否則使用用戶請(qǐng)求url中的主機(jī)名作為host;
- port_in_redirect設(shè)置為on時(shí),使用nginx監(jiān)聽的端口來構(gòu)造Location url,否則不設(shè)置port。
因此,上述三個(gè)配置項(xiàng)共同控制了Location url的結(jié)果,例如: “Location: http://server_name:port/index/”。 這三項(xiàng)配置的默認(rèn)值是absolute_redirect=on,server_name_in_redirect=off,port_in_redirect=on。因此默認(rèn)的Location url將是 “www.test.com/index/” 。
回到最開始的問題,https訪問跳轉(zhuǎn)到http的原因便可以梳理清楚了,作為靜態(tài)資源服務(wù)器的Nginx設(shè)置了301狀態(tài)碼,并且由于它監(jiān)聽的是80端口和使用http協(xié)議,假設(shè)瀏覽器訪問 “www.test.com/index” ,那么默認(rèn)構(gòu)造的Location url便是 “www.test.com/index/” ,并且API網(wǎng)關(guān)會(huì)直接將該響應(yīng)寫回給瀏覽器。瀏覽器收到301狀態(tài)碼的響應(yīng)后,解析出響應(yīng)頭的Location值,然后進(jìn)行跳轉(zhuǎn)。過程如下圖所示:
2.解決方案
最簡(jiǎn)便的解決方法便是,設(shè)置absolute_redirect為off,構(gòu)造相對(duì)路徑作為L(zhǎng)ocation url,示例如下:
server {listen 80;# 設(shè)置相對(duì)url重定向absolute_redirect off;server_name localhost;charset utf-8;access_log logs/access.log main;error_log logs/error.log;large_client_header_buffers 4 16k;client_max_body_size 300m;client_body_buffer_size 128k;location / {index index.html;root /var/www/index/;}} 復(fù)制代碼這樣以后,對(duì)于 "www.test.com/index" 的請(qǐng)求,Location響應(yīng)頭的值將等于 /index/。
與50位技術(shù)專家面對(duì)面20年技術(shù)見證,附贈(zèng)技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的Nginx 301跳转踩坑总结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring选择哪种注入方式
- 下一篇: Nginx配置SSI