1. 程式人生 > >HTTP狀態碼302、303和307的故事

HTTP狀態碼302、303和307的故事

一、狀態碼——302

    HTTP1.0在介紹302時說,如果客戶端發出POST請求後,收到服務端的302狀態碼,那麼不能自動的向新的URI傳送重複請求,必須跟使用者確認是否該重發,因為第二次POST時,環境可能已經發生變化(POST方法不是冪等的),POST操作會不符合使用者預期。但是,很多瀏覽器在這種情況下都會把POST請求變為GET請求。

    HTTP1.1在介紹302時說,如果客戶端發出非GET、HEAD請求後,收到服務端的302狀態碼,那麼就不能自動的向新URI傳送重複請求,除非得到使用者的確認。但是,很多瀏覽器都把302當作303處理了(注意,303是HTTP1.1才加進來的,其實從HTTP1.0進化到HTTP1.1,瀏覽器什麼都沒動),它們獲取到HTTP響應報文頭部的Location欄位資訊,併發起一個GET請求。

二、狀態碼——303和307

    從上面的介紹可以知道,HTTP1.1和HTTP1.0的302狀態碼意義是一樣的,瀏覽器對它的處理也是一樣的。POST方法的重定向在未詢問使用者的情況下就變成GET,這種不符合文件規範的問題依然存在。實踐在前而文件在後,HTTP1.1把這種POST變GET的行為納入了RFC文件:HTTP1.1新加入303和307狀態碼。

    文件中規定303狀態碼的響應,也就是上邊提到的現在瀏覽器對302狀態碼的處理:POST重定向為GET。

    HTTP1.1文件中307狀態碼則相當於HTTP1.0文件中的302狀態碼,當客戶端的POST請求收到服務端307狀態碼響應時,需要跟使用者詢問是否應該在新URI上發起POST方法,也就是說,307是不會把POST轉為GET的。

    文件也說到,為相容很多HTTP1.1之前的瀏覽器,服務端在需要發出303狀態碼時,會選擇用302狀態碼替代;而對於307的處理,則需要在響應實體中包含資訊,以便不能處理307狀態碼的使用者有能力在新URI中發起重複請求,也就是說,把重定向的頁面展示給使用者,讓使用者去點重定向URI連結(URI現在基本就是URL)。

三、總結

    303和307是HTTP1.1新加的伺服器響應文件的狀態碼,它們是對HTTP1.0中的302狀態碼的細化,主要用在對非GET、HEAD方法的響應上。文件規定:瀏覽器對303狀態碼的處理跟原來瀏覽器對HTTP1.0的302狀態碼的處理方法一樣;瀏覽器對307狀態碼處理則跟原來HTTP1.0文件裡對302的描述一樣。 

    303和307的存在,歸根結底是由於POST方法的非冪等屬性引起的。

    在HTTP1.1中,302理論上是要被放棄掉的,它被細化為303和307,但為了相容,它目前還在業界中大量使用,而303和307狀態碼我還沒遇到過。為什麼業界少使用303和307呢?對於GET和HEAD方法來說,307是沒必要存在的,用302或者303就可以滿足需求了,307僅在POST方法的重定向上有用處。所以我猜測它們少見的原因有兩方面:

1、POST方法重定向的使用場景太少,使得307狀態碼沒有用武之地;

2、GET方法雖然常需要使用的重定向,但使用302狀態碼也能正確運轉,再考慮到微乎其微的相容問題,也就沒有使用303的必要了。