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