今日讀書,無法理解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_302
2、RFC1945 http://tools.ietf.org/html/rfc1945#page-34
3、RFC2616 http://tools.ietf.org/html/rfc2616#section-10.3.3
cswuyg @ 2014.7.27