HTTP 狀態碼
前言
想要真正理解 HTTP 狀態碼,而不是死記硬背,最好先過一遍下圖。每個狀態碼都不是割裂開的,嘗試帶著圖理解,思考收到 HTTP 請求後的整個處理流程,同時理解 HTTP 協議的 Header,效率更高。
圖片比較模糊,被壓縮了,請轉 github 上的 for-GET/http-decision-diagram 專案看原圖。
100 Continue
表示目前為止一切正常,客戶端應該繼續請求,如果已完成請求則忽略.
為了讓伺服器檢查請求的首部,客戶端必須在傳送請求實體前,在初始化請求中傳送 Expect: 100-continue 首部並接收 100 Continue 響應狀態碼.
Expect
包含一個期望條件,表示伺服器只有在滿足此期望條件的情況下才能妥善地處理請求。
規範中只規定了一個期望條件,即 Expect: 100-continue,對此伺服器可以做出如下回應:
- 100 如果訊息頭中的期望條件可以得到滿足,使得請求可以順利進行的話,
- 417 (Expectation Failed) 如果伺服器不能滿足期望條件的話;也可以是其他任意表示客戶端錯誤的狀態碼(4xx)。
101 Switching Protocols
表示伺服器應客戶端升級協議的請求(Upgrade請求頭)正在進行協議切換。 例:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
複製程式碼
200 OK
表明請求已經成功. 預設情況下狀態碼為200的響應可以被快取。
201 Created
表示請求已經被成功處理,並且建立了新的資源。新的資源在應答返回之前已經被建立。
202 Accepted
表示伺服器端已經收到請求訊息,但是尚未進行處理。但是對於請求的處理確實無保證的,即稍後無法通過 HTTP 協議給客戶端傳送一個非同步請求來告知其請求的處理結果。
204 No Content
表示目前請求成功,但客戶端不需要更新其現有頁面。
使用慣例是,在 PUT 請求中進行資源更新,但是不需要改變當前展示給使用者的頁面,那麼返回 204 No Content。如果新建立了資源,那麼返回 201 Created 。如果頁面需要更新以反映更新後的資源,那麼需要返回 200 。
301 Moved Permanently
永久重定向。說明請求的資源已經被移動到了由 Location 頭部指定的 url 上,是固定的不會再改變。搜尋引擎會根據該響應修正。
儘管標準要求瀏覽器在收到該響應並進行重定向時不應該修改 http method 和 body,但是有一些瀏覽器可能會有問題。所以最好是在應對 GET 或 HEAD 方法時使用 301,其他情況使用 308 來替代 301
302 Found
臨時重定向。重定向狀態碼錶明請求的資源被暫時的移動到了由 Location 頭部指定的 URL 上。瀏覽器會重定向到這個URL,但是搜尋引擎不會對該資源的連結進行更新。
即使規範要求瀏覽器在重定向時保證請求方法和請求主體不變,但並不是所有的使用者代理都會遵循這一點,你依然可以看到有缺陷的軟體的存在。所以推薦僅在響應 GET 或 HEAD 方法時採用 302 狀態碼,而在其他時候使用 307 來替代,因為在這些場景下方法變換是明確禁止的。
在確實需要將重定向請求的方法轉換為 GET 的場景下,可以使用 303。例如在使用 PUT 方法進行檔案上傳操作時,需要返回確認資訊(例如“你已經成功上傳了xyz”)而不是上傳的資源本身,就可以使用這個狀態碼。
303 See Other
通常作為 PUT 或 POST 操作的返回結果,它表示重定向連結指向的不是新上傳的資源,而是另外一個頁面,比如訊息確認頁面或上傳進度頁面。而請求重定向頁面的方法要總是使用 GET。
304 Not Modified
說明無需再次傳輸請求的內容,也就是說可以使用快取的內容。這通常是在一些安全的方法(safe),例如GET 或HEAD,或在請求中附帶了頭部資訊: If-None-Match 或If-Modified-Since。
如果返回 200,響應會帶有頭部 Cache-Control,Content-Location,Date,ETag,Expires,和 Vary.
Last-Modified 和 If-Modified-Since
- 客戶端請求一個檔案(A)。 伺服器返回檔案A,並返回 Last-Modified。
- 客戶端收到響應後,快取檔案A 和 Last-Modified。
- 客戶端再次請求檔案A 時,發現該檔案有 Last-Modified ,那麼 header 離包含 If-Modified-Since,這個時間就是快取檔案的 Last-Modified。
- 服務端收到請求,只需要判斷這個時間和當前請求的檔案的修改時間就可以確定是返回 304 還是 200
If-Modified-Since 的主要缺點是隻能精確到秒的級別,一旦在一秒內出現多次修改,是無法判斷出已修改的狀態。所以一般用在對時間不太敏感的靜態資源。
ETag 和 If-None-Match
- 客戶端請求一個檔案(A)。 伺服器返回檔案A,並在給A加上一個 ETag。
- 客戶端收到響應後,並將檔案連同 ETag 一起快取。
- 客戶再次請求檔案A,會傳送 If-None-Match,內容是快取該檔案A的 Etag 值
- 伺服器檢查該 ETag,和計算出來的 Etag 匹配,來判斷檔案是否未被修改。如果未修改就直接返回 304 和一個空的響應體。否則返回 200 和 檔案。
當與 If-Modified-Since 一同使用的時候,If-None-Match 優先順序更高(假如伺服器支援的話)
307 Temporary Redirect
臨時重定向。類似 302,區別在於能夠確保請求方法和訊息主體不會發生改變。
308 Permanent Redirect
永久重定向。類似 301,區別在於能夠確保請求方法和訊息主體不會發生改變。
400 Bad Request
表示由於語法無效,伺服器無法理解該請求。客戶端不應該在未經修改的情況下重複此請求。
401 Unauthorized
說明由於缺乏目標資源要求的身份驗證憑證,傳送的請求未得到滿足。
這個狀態碼會與 WWW-Authenticate 首部一起傳送,其中包含有如何進行驗證的資訊。
WWW-Authenticate 和 Authorization
WWW-Authenticate 定義了應該用來訪問資源的認證方法。語法:
WWW-Authenticate: <type> realm=<realm>
複製程式碼
- type : Authentication type. A common type is "Basic".
- realm= : A description of the protected area. If no realm is specified,clients often display a formatted hostname instead.
例:
WWW-Authenticate: Basic
WWW-Authenticate: Basic realm="Access to the staging site",charset="UTF-8"
複製程式碼
Authorization 請求訊息頭含有伺服器用於驗證使用者代理身份的憑證,通常會在伺服器返回401 Unauthorized 狀態碼以及WWW-Authenticate 訊息頭之後在後續請求中傳送此訊息頭。語法:
Authorization: <type> <credentials>
複製程式碼
- type : Authentication type. A common type is "Basic".
- credentials :
- The username and the password are combined with a colon (aladdin:opensesame).
- The resulting string is base64 encoded (YWxhZGRpbjpvcGVuc2VzYW1l).
403 Forbidden
指的是伺服器端有能力處理該請求,但是拒絕授權訪問。進入該狀態後,不能再繼續進行驗證。該訪問是永久禁止的,並且與應用邏輯密切相關(例如不正確的密碼)
404 Not Found
說明伺服器端無法找到所請求的資源。返回該響應的連結通常稱為壞鏈(broken link)或死鏈(dead link),它們會導向連結出錯處理
404 不能說明請求的資源是臨時還是永久丟失。如果伺服器知道該資源是永久丟失,那麼應該返回 410 (Gone) 而不是 404 。
405 Method Not Allowed
表明伺服器禁止了使用當前 HTTP 方法的請求。需要注意的是,GET 與 HEAD 兩個方法不得被禁止,當然也不得返回狀態碼 405。
406 Not Acceptable
表示伺服器端不支援 Accept、Accept-Charset、Accept-Encoding、 Accept-Language header 所要求的。
Accept 和 Content-Type
Accept 用來告知客戶端可以處理的內容型別,這種內容型別用 MIME 型別來表示。伺服器從中選擇一項進行應用,並使用 Content-Type 應答頭通知客戶端。
Accept: <MIME_type>/<MIME_subtype>
Accept: <MIME_type>/*
Accept: */*
// Multiple types,weighted with the quality value syntax:
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
複製程式碼
- <MIME_type>/<MIME_subtype> : A single,precise MIME type,like text/html.
- <MIME_type>/* : A MIME type,but without any subtype. image/* will match image/png,image/svg,image/gif and any other image types.
- / : Any MIME type
- ;q= (q-factor weighting)
Accept-Encoding 和 Content-Encoding
Accept-Encoding 會將客戶端能夠理解的內容編碼方式——通常是某種壓縮演演算法——進行通知。服務端會從中選擇一個使用,並在響應報文首部 Content-Encoding 中通知客戶端。
Accept-Encoding: deflate,gzip;q=1.0,*;q=0.5
Content-Encoding: gzip
複製程式碼
409 Conflict
表示請求與伺服器端目標資源的當前狀態相沖突。
衝突最有可能發生在對 PUT 請求的響應中。例如,當上傳檔案的版本比伺服器上已存在的要舊,從而導致版本衝突的時候,那麼就有可能收到狀態碼為 409 的響應。
410 Gone
說明請求的內容在伺服器上不存在了,同時是永久性的丟失。如果不清楚是否為永久或臨時的丟失,應該使用404。
413 Payload Too Large
表示請求主體的大小超過了伺服器願意或有能力處理的限度,伺服器可能會(may)關閉連線以防止客戶端繼續傳送該請求。
如果“超出限度”是暫時性的,伺服器應該返回 Retry-After 首部欄位,說明這是暫時性的,以及客戶端可以在什麼時間後重試。
412 Precondition Failed
表示客戶端錯誤,意味著對於目標資源的訪問請求被拒絕。這通常發生在採用除 GET 和 HEAD 之外的方法進行條件請求時,由首部欄位 If-Unmodified-Since 或 If-None-Match 規定的先決條件不成立的情況下。
414 URI Too Long
表示客戶端所請求的 URI 超過了伺服器允許的範圍。
431 Request Header Fields Too Large
表示由於請求中的首部欄位的值過大,伺服器拒絕接受客戶端的請求。客戶端可以在縮減首部欄位的體積後再次傳送請求。
該響應碼可以用於首部總體體積過大的情況,也可以用於單個首部體積過大的情況。
500 Internal Server Error
表示所請求的伺服器遇到意外的情況並阻止其執行請求。
舉例:程式碼語法錯誤;php程式碼執行記憶體超了記憶體限制 memory_limit;nginx config 配置錯誤;
501 Not Implemented
表示request header 裡的 method 或 Content-* 時不被伺服器支援,無法被處理。另,伺服器必須支援的方法(即不會返回這個狀態碼的方法)只有 GET 和 HEAD。501 響應預設是可快取的。
502 Bad Gateway
表示作為閘道器或代理角色的伺服器,從上游伺服器(如tomcat、php-fpm)中接收到的響應是無效的。
舉例: php-fpm 掛掉了
503 Service Unavailable
表示伺服器尚未處於可以接受請求的狀態。通常造成這種情況的原因是由於伺服器停機維護或者已超載。該種響應應該用於臨時狀況下,與之同時,在可行的情況下,應該在 Retry-After 首部欄位中包含服務恢復的預期時間。
舉例:伺服器停機維護時,主動用503響應請求;nginx 設定限速之類的,超過限速,會返回503。
Retry-After
表示使用者代理需要等待多長時間之後才能繼續傳送請求。這個首部主要應用於以下幾種場景:
- When sent with a 503 response,this indicates how long the service is expected to be unavailable.
- When sent with a 429 response,this indicates how long to wait before making a new request.
- When sent with a redirect response,such as 301,this indicates the minimum time that the user agent is asked to wait before issuing the redirected request.
語法:
Retry-After: <http-date>
Retry-After: <delay-seconds>
複製程式碼
- : A date after which to retry.
- : A non-negative decimal integer indicating the seconds to delay after the response is received.
例:
Retry-After: Wed,21 Oct 2015 07:28:00 GMT
Retry-After: 120
複製程式碼
504 Gateway Timeout
表示閘道器或者代理的伺服器無法在規定的時間內獲得想要的響應。
舉例:程式碼執行時間超時,或死迴圈了。
問題
500 和 503 分別表示什麼,以及哪些情況下會用到。
401 和 403 的區別
- 401 Unauthorized 用於丟失或錯誤的身份驗證,響應頭包含 www-Authenticate 來描述如何驗證,通常由 Web 伺服器 返回,而不是應用程式,具有暫時性,伺服器會要求重試
- 403 Forbidden 是指已經驗過身份驗證,但是在某項請求資源操作上沒有許可權,具有永久性,與應用程式邏輯相關。
參考自