HTTP-308

 

原文地址:https://airbrake.io/blog/http-errors/308-permanent-redirect

308永久轉移:是什麼,怎麼修復它?

308是http的狀態返回碼,用來表示當前請求的資源已經永久的轉移到其他的uri,一般通過返回header的location字段展示。308code是近期在2015年4月加入到http標準庫的,文檔RFC7538有對308狀態碼的詳細描述。就像RFC7538描述的那樣308狀態碼適合和301,302,307這類狀態碼放一起。

事實上,有幾十種http狀態碼用來表示客戶端,web應用,web服務器和第三方web服務之間複雜的關係,所以找到產生http code碼的原因是一件非常困難的事情。應爲,還有很多潛在的http code碼,它們用來表示完全不同的狀態和事務,這就更加劇了區分它們的不同的困難,和找到產生它們的原因的困難,例如308 狀態碼。

通過幾個有用的點,整篇文章我們一起探索308狀態碼。我們也會用幾個簡單又實用的方法修復引起308 狀態碼的一般性問題。讓我們開始吧。

服務端問題

所有的3XX類的狀態碼都是定向類問題。這類狀態碼提示客戶端(例如你的瀏覽器)需要執行附加的動作來完成請求動作,或者獲取到想要的資源。3XX類的狀態碼很明顯和5XX類的狀態碼不同,5XX類的狀態碼明顯包含着服務段的錯誤信息。例如503錯誤,服務不可用,我們可以通過這個狀態碼探索一個網站近一年內臨時不可用。不同於一個5xx錯誤能夠明確的表示這是服務端的錯誤,3XX類的幾乎不可能準確的表示一個錯誤,它僅僅只能提示服務的行爲或者配置有可能有問題,不表示服務端有bug或者錯誤。

308狀態碼和301狀態碼很相似,着篇文章講述什麼是301錯誤碼和如何修復它https://airbrake.io/blog/http-errors/301-moved-permanently。像前文提到的那樣,RFC1945 HTTP/1.0 標準文檔明確的聲明301沒必要通知客戶端(例如瀏覽器)自動重定向POST請求到GET請求。然而,很多客戶端錯誤的將post的請求轉化成get請求,並引出了不可預知的問題。

爲了明確的控制這個從POST請求轉化成GET請求,HTTP標準包含以下碼:

    301:資源已經永久的轉移,允許將POST改成GET

    307:  資源臨時轉移,不允許將post改成get

    302:   資源臨時轉移,允許將POST改成GET

你可以看到,這組三個狀態碼,缺少一個狀態碼用來表示資源永久轉移,不允許將post改成get。這個正是308錯誤碼的意義。

出現308狀態碼一般情況下不需要用戶特別關心。所有的流行的瀏覽器都會自動的檢測308狀態碼,並且自動的轉到相應的地址。服務端返回308狀態碼的時候還會包含location頭,返給客戶端。location header 會提示新的資源地址。例如,如果客戶端通過post方法嘗試登錄https://airbrake.io,web服務器可能會重定向到不同的地址,如https://airbrake.io/login。在這種場景下,服務器將返回308狀態碼和Location: https://airbrake.io/login header。這是告訴客戶端(瀏覽器)post請求已經被服務器接受,但是資源已經被永久的移動到了Location header : https://airbrake.io/login。

區分使用308和其它類似的錯誤碼的場景同樣非常重要,例如上面提到的307狀態碼。307狀態碼告訴客戶端Location URI只是臨時的資源地址,後面所有的請求會繼續訪問原始的地址。相反308狀態碼告訴客戶端,這次轉移是永久轉移,後面所有的請求將訪問新的地址。

另外,因爲308 狀態碼預示着服務端的應用有什麼錯誤,我們可以忽略客戶端的。如果你在嘗試診斷你的應用,你可以立刻忽略客戶端的代碼和插件,例如html,css,js。這不僅僅適用於web網站。許多智能手機app也是一樣。在你使用app的時候,出現了308狀態碼,一般不會是安裝在你手機上或測試設備上的app的原因。相反,它可能是服務端的問題。

如果你的應用產生了意想不到的308狀態碼,這裏有很多步驟幫助你定位問題,所以下面讓我們一起探索。

首先做一個完整的備份

無論何事,最好在一開始就做好安全措施,而不是在半路上去擰螺絲,去後悔。因此,在嘗試修復和更改你的系統之前,很有必要先對你的應用,數據庫等做一個備份。更甚至你有能力的話,完全拷貝當前應用到一個不公開的平臺上。這將提供給你一個非常乾淨的環境,去測試爲解決問題而做的潛在的修改,這樣也不會有安全問題,也不會以侵犯你的線上服務。

診斷308狀態碼

308狀態碼預示着請求的資源已經永久的遷移到新的URI,這個一般通過response header的location指定。然而,出現308也許本身就是一個誤導,因爲它完全有可能是服務器配置錯誤引起,服務器的錯誤配置可能會引起不合適的response同時帶着308,而不是標準的200。這樣,大部分時候通過診斷產生308狀態碼的代碼能解決問題。

如果你的應用返回了308而它不應該返回,這個問題很多人都應該遇到過,神奇般的阻止應用爲用戶提供服務。下面我們根據一些檢測點和技巧來解決這個問題。如果這些技巧也沒有用的話,不要忘記去goole找答案。輸入和你的問題相關的詞條加上308,例如你的應用的名稱或者web服務器軟件。你將有機會找到遇到過此問題並解決這個問題的人。

檢查服務端

這裏有幾條祕訣會幫助你檢查在服務端是什麼原因引起308。

確認你的服務配置

你的應用很可能運行在nginx或者apache服務器上。在文章發佈時,這兩個服務器軟件佔有84%的市場佔有率。這樣,第一步要做的就是檢查配置文件裏跳轉相關的指令。

要找到你的應用使用的是哪個服務器,你需要找到關鍵文件。如果你使用的是Apache那就去網站的根目錄找.htaccess文件。例如,如果你的應用使用了共享的主機,相應的你需要有一個對應的賬號。在這種情況下,應用的根目錄像這樣/home/<username>/public_html/,而 .htaccess 將在 /home/<username>/public_html/.htaccess。

如果你已經定位了.htaccess文件,使用文本編輯器打開它找到RewriteXXX指令。仔細檢查所有的規則是否正確,然而,基本的觀念是rewriteCond指令定義基本的模型匹配傳入的URL。當用戶訪問網站時候,如果一個url被一個或者多個Rewritecond匹配上,則將會定向到最合適的地址。

例如,這裏有一個簡單的RewriteCond和RewriteRule綁定,它將匹配所有的post請求,通過308將airbrake.io重定向到https://airbrake.io/login

RewriteEngine on
RewriteCond %{HTTP_HOST} ^airbrake.io$
RewriteRule ^(.*)$ http://airbrake.io/login$1 [R=308]

注意RewriteRule最後的標籤,這個標籤用來明確的聲明返回的狀態碼是308,指示客戶端請求應該重定向到指定的URI,同時仍然使用原來的HTTP方法(本例是指POST)。這樣,如果你在.htaccess發現任何奇怪的RewriteCond或者RewriteRule指令,可以嘗試去註釋它們,然後重啓服務去看看是否解決了問題。

另一方面,如果你的用的是nginx服務,你需要找一個和apache完全不同的配置文件。一般情況下這個文件是nginx.conf,並且這個文件一般放在以下共有目錄下:/usr/local/nginx/conf/etc/nginx, 或者 /usr/local/etc/nginx。一旦定位文件後,使用文件編輯器打開nginx.conf,找到使用308的return或者rewrite指令。例如,這有一個簡單的block指令,配置一個虛擬服務將POST請求從airbrake.io定向到airbrake.io/login。

server {
    listen 80;
    listen 443 ssl;
    server_name airbrake.io;
    if ($request_method = POST) {
        return 308 https://airbrake.io/login$request_uri;
    }
}

nginx的Return指令和Apache裏面的RewriteCond和RewriteRule指令相似,它們都趨向於包含複雜的基於文本的模式用於搜索。無論哪種方式,通讀nginx.conf文件找到不正常的包含308標籤的return和rewrite指令。將不正常的指令註釋掉,重啓服務檢查是否能解決問題。

檢查日誌

 幾乎所有的應用都保存服務端日誌。應用日誌代表了應用的操作歷史,例如哪個頁面被訪問了,哪個服務被鏈接了,它提供了哪個數據庫的數據,等等。服務日誌記錄了硬件的實際運行情況,也會提供服務的運行狀態。如果你使用CMS可以goole“logs[PLATFORM_NAME]”,如果你正在運行一個客戶端應用可以goole“logs[PROGRAMMING_LANGUAGE]”和“logs[OPERATING_SYSTTEM]”,通過日誌信息可以獲取到有關問題的更多日誌。

調試你的應用代碼

如果以上都失敗了,那麼它有可能是你代碼的問題,引起的問題。試着通過手動調試你的代碼,來定位問題。在理想環境下,將整個應用拷貝到開發機器,一步一步調試程序,這將允許你重現308的時候錯誤。

無論是什麼原因引起的,308在你的應用中的出現預示着你可能需要一個錯誤管理工具在將來幫助你自動檢測這類錯誤。工具的最大好處是當錯誤出現的時候能立刻通知你和你的團隊。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章