HTTP狀態碼30二、303和307的故事

《HTTP權威指南》第3章在講解30X狀態碼時,徹底沒有講清楚爲何要有30二、30三、307,以及他們的關係,一句「問題出在HTTP/1/1」讓我一頭霧水,莫名其妙;而第五章在講重定向響應時,沒有說到如今很常見的302,反而是說我從沒遇到過的303和307。非常迷惑,對於這3個狀態碼,WiKi和RFC文檔都有詳解,下面我以個人思惟添油加醋的描述一遍。

1、狀態碼——302html

    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請求。

2、狀態碼——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)。

3、總結服務器

    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方法的重定向上有用處。因此我猜想它們少見的緣由有兩方面:一、POST方法重定向的使用場景太少,使得307狀態碼沒有用武之地;二、GET方法雖然常須要使用的重定向,但使用302狀態碼也能正確運轉,再考慮到微乎其微的兼容問題(如今的瀏覽器怎麼可能不支持HTTP1.1呢!),也就沒有使用303的必要了。
   
本文轉自:http://www.cnblogs.com/cswuyg/p/3871976.html
相關文章
相關標籤/搜索