淺析http狀態碼301、302、303、307、308區別(轉載)

http的重定向我們經常是張口就來,整個流程也非常簡單,服務端HTTP返回碼是30x,頭裏面的Location字段代表新的URL。如下圖所示:

但重定向也還是有需要深入探討地方,返回碼不僅有我們經常使用301和303還有302 307 308 它們有啥區別呢。可以按照是否緩存和重定向方法,兩個維度去拆分。

  緩存(永久重定向) 不緩存(臨時重定向)
轉GET 301 302、303
方法保持 308 307

如果是永久重定向那麼瀏覽器客戶端就會緩存此次重定向結果,下次如果有請求則直接從緩存讀取,譬如我們切換域名,將所有老域名的流量轉入新域名,可以使用永久重定向。

如果只是臨時重定向那麼瀏覽器則不會緩存,譬如我們的服務臨時升級,會使用臨時重定向。

方法保持的意思是原請求和重定向的請求是否使用相同的方法,譬如原請求是POST提交一個表單,如果是301重定向的話,重定向的請求會轉爲GET重新提交,如果是308則會保持原來POST請求不變。

 

 

RFC協議規範

  • 301 Moved Permanently,永久重定向
  • 302 Found
  • 303 See Other
  • 307 Temporary Redirect
  • 308 Permanent Redirect 永久重定向

 

 

基本結論

  • 3XX開頭的HTTP狀態碼都表示重定向的響應。
  • 301、308是永久重定向;302、303、307是臨時重定向。
  • 301、302是http 1.0的內容,303、307、308是http1.1的內容。
  • 301和302本來在http/1.0規範中是不允許重定向時改變請求method的(將POST改爲GET),實際許多瀏覽器實現的時候允許重定向時改變請求method。這就出現了規範和實現不一致的問題
  • 302,303,307的出現,都是基於HTTP/1.1兼容HTTP/1.0規範和實現的差異性;
    • 303的出現是允許重定向時改變請求method
    • 307、308則不允許重定向時改變請求method
    • 此外303響應禁止被緩存。

 

 

HTTP/1.0

301

301狀態碼在HTTP 1.0和HTTP 1.1規範中均代表永久重定向,對於資源請求,原來的url和響應頭中location的url而言,資源應該對應location中的url。對於post請求的重定向,還是需要用戶確認之後才能重定向,並且應該以post方法發出重定向請求。

關於post請求重定向用戶確認的問題,實際上瀏覽器都沒有實現;而且post請求的重定向應該發起post請求,這裏瀏覽器也並不一定遵守,所以說HTTP規範的實現並未嚴格按照HTTP規範的語義。

在301中資源對應的路徑修改爲location的url,在SEO中並未出現問題,但是在302中就出現了302劫持問題

 

302

在http 1.0規範中,302表示臨時重定向,location中的地址不應該被認爲是資源路徑,在後續的請求中應該繼續使用原地址。

  • 規範
    • 原請求是post,則不能自動進行重定向;原請求是get,可以自動重定向;
  • 實現
    • 瀏覽器和服務器的實現並沒有嚴格遵守HTTP中302的規範,服務器不加遵守的返回302,瀏覽器即便原請求是post也會自動重定向,導致規範和實現出現了二義性,由此衍生了一些問題,譬如302劫持,因此在HTTP 1.1中將302的規範細化成了303和307,希望以此來消除二義性。
  • 302劫持
    • A站通過重定向到B站的資源xxoo,A站實際上什麼都沒做但是有一個比較友好的域名,web資源xxoo存在B站並由B站提供,但是B站的域名不那麼友好,因此對搜索引擎而言,可能會保存A站的地址對應xxoo資源而不是B站,這就意味着B站出了資源版權、帶寬、服務器的錢,但是用戶通過搜索引擎搜索xxoo資源的時候出來的是A站,A站什麼都沒做卻被搜索引擎廣而告之用戶,B站做了一切卻不被用戶知道,價值被A站竊取了。

 

 

HTTP/1.1

301

和http 1.0規範中保持一致,注意資源對應的路徑應該是location中返回的url,而不再是原請求地址。

 

302

在HTTP 1.1中,實際上302是不再推薦使用的,只是爲了兼容而作保留。規範中再次重申只有當原請求是GET or HEAD方式的時候才能自動的重定向,爲了消除HTTP 1.0中302的二義性,在HTTP 1.1中引入了303和307來細化HTTP 1.0中302的語義。

 

303

在HTTP 1.0的時候,302的規範是原請求是post不可以自動重定向,但是服務器和瀏覽器的實現是運行重定向。

把HTTP 1.0規範中302的規範和實現拆分開,分別賦予HTTP 1.1中303和307,因此在HTTP 1.1中,303繼承了HTTP 1.0中302的實現(即原請求是post,也允許自動進行重定向,結果是無論原請求是get還是post,都可以自動進行重定向),而307則繼承了HTTP 1.0中302的規範(即如果原請求是post,則不允許進行自動重定向,結果是post不重定向,get可以自動重定向)

 

307

在http 1.1規範中,307爲臨時重定向,注意劃紅線的部分,如果重定向307的原請求不是get或者head方法,那麼瀏覽器一定不能自動的進行重定向,即便location有url,也應該忽略

也就是307繼承了302在HTTP 1.0中的規範(303繼承了302在HTTP 1.0中的實現)。

 

308

308與301定義一致,唯一的區別在於,308狀態碼不允許瀏覽器將原本爲POST的請求重定向到GET請求上。

 

 

小結

在HTTP 1.0規範中,302的規範並沒有被服務器和瀏覽器遵守,即規範和實現出現了二義性,因此在HTTP 1.1中,將302的規範和實現拆分成了303和307。

 

瀏覽器對307狀態的處理規則和302狀態相同。之所以將值307引入到HTTP/1.1中,是因爲,甚至在最初的消息是POST的情況下,許多瀏覽器依舊錯誤地跟隨302響應中的重定向信息,瀏覽器應該只在接收到303狀態碼時纔跟從POST請求的重定向信息。引入這個新狀態是爲了消除二義性:如果接收到303響應,則繼續進行GET和POST請求的重定向;如果接收到307響應,對於GET請求的重定向,則繼續進行;但對於POST請求的重定向,則不再繼續下去。這是HTTP/1.1新引入的狀態碼。

 

 

參考文獻:

淺析http狀態碼301、302、303、307、308區別

HTTP中的301、302、303、307、308

 

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