http狀態碼204/206/200/302/303/307


HTTP的狀態碼有很多種,主要有1xx(臨時響應)、2xx(成功)、3xx(已重定向)、4xx(請求錯誤)以及5xx(服務器錯誤)五個大類,每個大類還對應一些具體的分類。平時我們接觸比較多的是200、400、500等。

這里我們主要討論一下狀態碼204,在HTTP RFC 2616中關於204的描述如下:

If the client is a user agent, it SHOULD NOT change its document view from that which caused the request to be sent. This response is primarily intended to allow input for actions to take place without causing a change to the user agent’s active document view, although any new or updated metainformation SHOULD be applied to the document currently in the user agent’s active view.

意思等同於請求執行成功,但是沒有數據,瀏覽器不用刷新頁面.也不用導向新的頁面。如何理解這段話呢。還是通過例子來說明吧,假設頁面上有個form,提交的url為http-204.htm,提交form,正常情況下,頁面會跳轉到http-204.htm,但是如果http-204.htm的相應的狀態碼是204,此時頁面就不會發生轉跳,還是停留在當前頁面。另外對於a標簽,如果鏈接的頁面響應碼為204,頁面也不會發生跳轉。

所以對於一些提交到服務器處理的數據,只需要返回是否成功的情況下,可以考慮使用狀態碼204(也就是XMLHttpRequest.status)來作為返回信息,從而省掉多余的數據傳輸。

$.ajax({
            type: "POST",
            beforeSend: function(xhr){xhr.setRequestHeader('__RequestVerificationAntiCSRFToken', $("#hidden-CSRFToken").val());},
            url: $(this).data('targetUrl'), 
            cache: false,        
            data:post_data,
            dataType:"json",
            async: true,
            error: function(jqXHR, error, errorThrown) {
                alert(jqXHR.status);          
                },
            success: function(data) {
               //...
               }
  });

上次我們講了HTTP/304響應,今天我們繼續討論另外三種可能讓Fiddler用戶感到困惑的請求或響應類型.

下面的截圖中有三條Web會話,每一條都返回了不同的狀態碼,但都在HTTP/2xx范圍內:

image

HEAD請求方法

第一個請求返回了HTTP/200,但你應該注意到了,服務器並沒有返回響應體.如果你在Inspectors選項卡中查看一下,就會發現客戶端使用的是HEAD請求方法.HEAD方法允許客戶端僅向服務器請求某個資源的響應頭,而不要真正的下載該資源本身.服務器返回的響應頭應該和客戶端使用GET方法請求該資源時返回的請求頭相同,比起GET方法,只是省略了響應體.

image

從上圖中可以看出,如果客戶端使用GET而不是HEAD方法請求該資源,服務器就應該會返回6623字節大小的響應體.還可以看出,該資源的類型為text/html以及它的編碼為UTF-8.客戶端可以使用HEAD請求來收集相關信息以確定如何操作該資源.例如,在IE中,如果一個OBJECT元素缺少TYPE參數,瀏覽器就會發送一個HEAD請求,目標URL為這個OBJECT元素的SRC屬性指定的URL.然后瀏覽器就能夠根據響應中的Content-Type頭知道這是哪種類型的OBJECT.

HTTP/204響應

會話列表中的第二條會話返回了HTTP/204響應.從Content-Length響應頭可以看出,該響應沒有響應體,狀態碼描述為“No Content”:

image

你也許會有疑問:“返回一個沒有響應體的HTTP/200響應不行嗎?”

如果沒有響應體,則在大多數場景下,這兩種響應碼完全等效,但有一種情況下,HTTP/204響應會讓瀏覽器有不同的表現.這種情況就是當用戶在瀏覽器窗口window或者frame/iframe框架中導航的時候.

  • 如果導航到的URL返回了一個沒有響應體的HTTP/200響應,則頁面將會顯示一個空白文檔(就是一片白色).頁面的URL地址也會變成新指定的URL.
  • 如果服務器返回的是一個HTTP/204響應,當前頁面不會有任何變化,就好像根本沒有進行導航操作一樣.頁面的URL地址也保持不變.

HTTP/205響應碼很少見,它類似於HTTP/204,除了頁面保留在當前文檔不變以外,多了一步操作,就是要清空當前文檔內所有表單控件的內容.

HTTP/206響應

最后一條會話返回了HTTP/206 “Partial Content”響應.這種響應是在客戶端表明自己只需要目標URL上的部分資源的時候返回的.這種情況經常發生在客戶端繼續請求一個未完成的下載的時候(通常是當客戶端加載一個體積較大的嵌入文件,比如視屏或PDF文件),或者是客戶端嘗試實現帶寬遏流的時候.

你可以通過Range請求頭辨認出一個部分內容請求.該請求頭表明了客戶端需要請求資源的哪一部分:

image

在上圖的請求中,客戶端告訴服務器,它需要該視屏文件中從172,032到13,325,503字節范圍內的數據.

在大多數情況下,客戶端還會發送一些條件請求頭,讓服務器來辨別該返回哪個版本的資源.在上圖的請求中,客戶端把它在上次接收該資源的0到172032字節部分請求中服務器返回的ETag響應頭作為了本次請求的If-Match請求頭發送了出去,同樣還把上次響應中的Last-Modified響應頭用If-Unmodified-Since請求頭發送了出去.

如果服務器發現該資源的版本與客戶端所請求的版本不匹配,則會返回一個HTTP/412 Precondition Failed響應.如果客戶端使用If-Range請求頭而不是If-Match發送了上次收到的ETag響應頭的值,且服務器發現客戶端請求的版本與當前資源的版本不匹配,則服務器會返回整個資源數據.如果客戶端需要完整的資源數據,使用If-Range可以減少一個網絡請求.

服務器的Content-Range響應頭表明了返回的是文件的哪一部分,Content-Length響應頭表明了該部分文件的大小:
image

你也許注意到了Accept-Ranges響應頭,服務器發送這個頭的目的是讓客戶端知道服務器接受以字節為單位的部分內容請求.

如果你在Fiddler中看到了一個HTTP/206響應,但你需要的是一個完整的文件(比如你想保存一個完整的視屏文件),你可以選中該會話按下U鍵,或者按住Ctrl鍵點擊工具欄中的Replay按鈕,執行無條件請求。

 

    今日讀書,無法理解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的必要了。
 
參考資料:
2、RFC1945 http://tools.ietf.org/html/rfc1945#page-34
3、RFC2616 http://tools.ietf.org/html/rfc2616#section-10.3.3

在HTTP1.1協議下,HTTP狀態碼總共可分為5大類

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
1 xx:信息響應類,表示接收到請求並且繼續處理
2 xx:處理成功響應類,表示動作被成功接收、理解和接受
3 xx:重定向響應類,為了完成指定的動作,必須接受進一步處理
4 xx:客戶端錯誤,客戶請求包含語法錯誤或者是不能正確執行
5 xx:服務端錯誤,服務器不能正確執行一個正確的請求
 
100 ——客戶必須繼續發出請求
101 ——客戶要求服務器根據請求轉換HTTP協議版本
200 ——交易成功
201 ——提示知道新文件的URL
202 ——接受和處理、但處理未完成
203 ——返回信息不確定或不完整
204——請求收到,但返回信息為空
205 ——服務器完成了請求,用戶代理必須復位當前已經瀏覽過的文件
206 ——服務器已經完成了部分用戶的GET請求
300 ——請求的資源可在多處得到
301 ——刪除請求數據
302 ——在其他地址發現了請求數據
303 ——建議客戶訪問其他URL或訪問方式
304 ——客戶端已經執行了GET,但文件未變化
305 ——請求的資源必須從服務器指定的地址得到
306 ——前一版本HTTP中使用的代碼,現行版本中不再使用
307 ——申明請求的資源臨時性刪除
400 ——錯誤請求,如語法錯誤
401 ——請求授權失敗
402 ——保留有效ChargeTo頭響應
403 ——請求不允許
404 ——沒有發現文件、查詢或URl
405 ——用戶在Request-Line字段定義的方法不允許
406 ——根據用戶發送的Accept拖,請求資源不可訪問
407 ——類似 401 ,用戶必須首先在代理服務器上得到授權
408 ——客戶端沒有在用戶指定的餓時間內完成請求
409 ——對當前資源狀態,請求不能完成
410 ——服務器上不再有此資源且無進一步的參考地址
411 ——服務器拒絕用戶定義的Content-Length屬性請求
412 ——一個或多個請求頭字段在當前請求中錯誤
413 ——請求的資源大於服務器允許的大小
414 ——請求的資源URL長於服務器允許的長度
415 ——請求資源不支持請求項目格式
416 ——請求中包含Range請求頭字段,在當前請求資源范圍內沒有range指示值,請求也不包含If-Range請求頭字段
417 ——服務器不滿足請求Expect頭字段指定的期望值,如果是代理服務器,可能是下一級服務器不能滿足請求
500 ——服務器產生內部錯誤
501 ——服務器不支持請求的函數
502 ——服務器暫時不可用,有時是為了防止發生系統過載
503 ——服務器過載或暫停維修
504 ——網關超時,服務器使用另一個服務如tomcat或ftp來響應用戶,解決方法:等待時間設定值加長比如10分鍾,或優化后端程序。axios提示為request failed with statuscode 504
505 ——服務器不支持或拒絕支請求頭中指定的HTTP版本


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM