這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。 今日讀書,無法理解HTTP302、303、307狀態代碼的來龍去脈,決定對其做深究並總結於本文。 《HTTP權威指南》第3章在講解30X狀態代碼時,完全沒有講清楚為什麼要有302、303、307,以及他們的關係,一句“問題出在HTTP/1/1”讓我一頭霧水,莫名其妙;而第五章在講重新導向響應時,沒有說到現在很常見的302,反而是說我從沒遇到過的303和307。很是迷惑,對於這3個狀態代碼,WiKi和RFC文檔都有詳解,下面我以我的思維添油加醋的描述一遍。
一、狀態代碼——302
RFC1945(http://tools.ietf.org/html/rfc1945#page-34),也就是HTTP1.0在介紹302時說,如果用戶端發出POST請求後,收到服務端的302狀態代碼,那麼不能自動的向新的URI發送重複請求,必須跟使用者確認是否該重發,因為第二次POST時,環境可能已經發生變化(嗯,POST方法不是等冪的),POST操作會不符合使用者預期。但是,很多瀏覽器(user agent我描述為瀏覽器以方便介紹)在這種情況下都會把POST請求變為GET請求。 RFC2616(http://tools.ietf.org/html/rfc2616#section-10.3.3),也就是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的。 從網路上搜尋到這個說法“303:對於POST請求,它表示請求已經被處理,用戶端可以接著使用GET方法去請求Location裡的URI。 307:對於POST請求,表示請求還沒有被處理,用戶端應該向Location裡的URI重新發起POST請求。”,從上面的介紹可以明白,這個說法是臆想而已,文檔並沒有這麼說,而業界是否統一如此處理,還不好說,我沒有抓到過307和303的包。 文檔也說到,為相容很多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狀態代碼也能正確運轉,再考慮到微乎其微的相容問題(現在的瀏覽器怎麼可能不支援HTTP1.1呢!),也就沒有使用303的必要了。 本文所在:http://www.cnblogs.com/cswuyg/p/3871976.html 參考資料:1、HTTP 302 wiki http://en.wikipedia.org/wiki/HTTP_3022、RFC1945 http://tools.ietf.org/html/rfc1945#page-343、RFC2616 http://tools.ietf.org/html/rfc2616#section-10.3.3 cswuyg @ 2014.7.27