本文從以下幾個方面,循序漸進走進 HTTP 狀態碼
- 狀態碼用來做什么的
- 常見狀態碼有哪些
- 容易爭論的點
狀態碼用來做什么的
HTTP 狀態行中使用狀態碼(Status Code)和原因短語(Reason Phrase)來簡單描述請求的結果

- Version:版本號,例如 HTTP/2
- Reason:是狀態碼的簡短文字描述,例如“OK”“Not Found”等等,也可以自定義,它其實對狀態碼的解釋說明
- Status Code:狀態碼,表示服務器對請求的處理結果
這里我們重點介紹狀態碼,狀態碼是用以表示 HTTP 響應狀態的 3 位數字代碼,由RFC 2616規范定義。 合理的狀態碼不僅可以讓用戶或者瀏覽器做出更加合適的進一步操作(例如繼續發送請求、切換協議,重定向跳轉等),而且可以讓客戶端代碼更加易於理解和維護 。
RFC 把狀態碼分成五類,分別是:
- 1××: 請求已被接受正被處理,表示目前是協議處理的中間狀態,還需要后續的操作
- 2××: 請求成功處理,報文已經收到並被正確處理
- 3××: 代表需要客戶端采取進一步的操作才能完成請求,例如重定向,通常,這些狀態碼用來重定向,后續的請求地址(重定向目標)在本次響應的Location域中指明
- 4××: 客戶端錯誤,請求報文有誤,服務器無法處理
- 5××: 服務器錯誤,服務器在處理請求時內部發生了錯誤
常見狀態碼有哪些
1xx
1xx 是很陌生的,代表請求已被接受,需要繼續處理。這類響應是臨時響應,標示客戶應該等待服務器采取進一步行動。
我們最常見的是 101(Switching Protocols)
101(Switching Protocols)
服務器已經理解了客戶端的請求,並根據 Upgrade 消息頭切換協議。
在 http header怎么判斷協議是不是websocket 我們提到過,http 發送請求給服務器,服務器通過判斷 header 中是否包含 Connection: Upgrade 與 Upgrade: websocket 來判斷當前協議是否要升級到 websocket ,如果服務器同意進行 WebSocket 連接時,返回響應碼 101

2xx
表示請求已成功被服務器接收、理解、並接受
常見的有
- 200
- 204
- 206:
200(OK)
最常見的,表示請求成功
204(NO Content)
與 200 基本相同,但響應頭后沒有 body 數據
206(Partial Content)
分片傳輸,每次只返回了請求資源的 部分 ,常用於實現斷點續傳或者將一個大文檔分解為多個下載段同時下載
請求頭中包含 Range 字段時,響應需要只返回 Range 指定的那一段。響應中應包含 Content-Range 來指示返回內容的范圍
例如:
'Range':byte=5001-10000 // 表示本次要請求資源的5001-10000字節的部分
這種情況下,如果服務器接受范圍請求並且成功處理,就會返回 206 ,並且在響應的頭部返回
http://www.wanjiashidai.com/?cate=1 // 表示整個資源有10000字節,本次返回的范圍為 5001-10000字節
3xx
這類狀態碼代表需要客戶端采取進一步的操作才能完成請求。通常,這些狀態碼用來重定向, 重定向目標在本次響應的 Location 頭字段中指明
主要有以下 9 種狀態碼:
| 狀態碼 | 狀態短語 | 狀態含義 |
|---|---|---|
| 300 | Multiple Choices | 當請求的 URL 對應有多個資源時(如同一個 HTML 的不同語言的版本),返回這個代碼時,可以返回一個可選列表,這樣用戶可以自行選擇。通過 Location 頭字段可以自定首選內容。 |
| 301 | Moved Permanetly | 當前請求的資源已被移除時使用,響應的 Location 頭字段會提供資源現在的 URL。直接使用 GET 方法發起新情求。 |
| 302 | Found | 與 301 類似,但客戶端只應該將 Location 返回的 URL 當做臨時資源來使用,將來請求時,還是用老的 URL。直接使用 GET 方法發起新情求。 |
| 303 | See Other | 用於在 PUT 或者 POST 請求之后進行重定向,這樣在結果頁就不會再次觸發重定向了。 |
| 304 | Not Modified | 資源未修改,表示本地緩存仍然可用。 產生這個狀態的前提是:客戶端本地已經有緩存的版本,並且在 Request 中告訴了服務端,當服務端通過時間或者 Etag,發現沒有更新的時候,就會返回一個不含 body 的 304 狀態 |
| 305 | Use Proxy | 用來表示必須通過一個代理來訪問資源,代理的位置有 Location 頭字段給出 |
| 306 | Switch Proxy | 在最新版的規范中,306 狀態碼已經不再被使用。最初是指“后續請求應使用指定的代理”。 |
| 307 | Temporary Redirect | 與 302 類似,但是使用原請求方法發起新情求。 |
| 308 | Permanent Redirect | 與 301 類似,但是使用原請求方法發起新情求。 |
這 9 種狀態碼可以分成 3 大類,分別是:永久重定向、臨時重定向以及特殊重定向
- 永久重定向: 301 、 308
- 臨時重定向: 302、303、307
- 特殊重定向: 300、304、305、306
永久重定向
301 和 308 都屬於永久重定向,301 本來在規范中是不允許重定向時改變請求方法的(將POST改為GET),但是許多瀏覽器卻允許重定向時改變請求方法(這是一種不規范的實現)
308 的出現也是給上面的行為做個規范,不過是不允許重定向時改變請求方法。
| Permanent | Temporary | |
|---|---|---|
| Allows changing the request method from POST to GET. | 301 | 302 |
| Does not allow changing the request method from POST to GET. | 308 | 307 |
臨時重定向
302、303、307 都屬於臨時重定向,臨時是指訪問的資源可能暫時先用location的URI訪問,但舊資源還在的,下次你再來訪問的時候可能就不用重定向了
302 和 307 的關系類似於 301 和 308,303通常用來在創建、修改和刪除時展示臨時的進度頁
特殊重定向
除此之外,300/304/305/306 可以歸屬到特殊重定向類。這里重點說一下 304,304 是 HTTP 緩存中的一個重要內容,表示資源未修改,相當於將資源重定向到本地緩存。
304 又是一個每個前端必知必會的狀態,產生這個狀態的前提是:客戶端本地已經有緩存的版本,並且在 Request 中告訴了服務端,當服務端通過時間或者 Etag,發現沒有更新的時候,就會返回一個不含 body 的 304 狀態
4xx
表示客戶端發送的請求報文有誤,服務器無法處理,它就是真正的“錯誤碼”含義了
400(Bad Request)
由於明顯的客戶端錯誤(例如,格式錯誤的請求語法,太大的大小,無效的請求消息或欺騙性路由請求),服務器不能或不會處理該請求
403(Forbidden)
表示服務器禁止訪問資源。原因可能多種多樣,例如信息敏感、法律禁止等,如果服務器友好一點,可以在 body 里詳細說明拒絕請求的原因,不過現實中通常都是直接給一個“閉門羹”
404(Not Found)
請求失敗,請求所希望得到的資源未在服務器上發現,但允許用戶的后續請求。
5xx
服務器錯誤,服務器在處理請求時內部發生了錯誤
500(Internal Server Error)
通用錯誤消息,服務器遇到了一個未曾預料的狀況,導致了它無法完成對請求的處理。沒有給出具體錯誤信息。
501(Not Implemented)
服務器不支持當前請求所需要的某個功能。當服務器無法識別請求的方法,並且無法支持其對任何資源的請求
502(Bad Gateway)
作為網關或者代理工作的服務器嘗試執行請求時,從上游服務器接收到無效的響應
503(Service Unavailable)
表示服務器當前很忙,暫時無法響應服務,我們上網時有時候遇到的“網絡服務正忙,請稍后重試”的提示信息就是狀態碼 503
容易爭論的點
301、302 和 307區別(對 SEO 的影響)
- 301:可通知搜索引擎蜘蛛,表示某個網頁或網站已被永久移動到新位置
- 302:搜索引擎蜘蛛會繼續抓取原有位置並將其編入索引,因此某個頁面或網站已被移動時,不要使用此代碼來通知搜索引擎蜘蛛。
- 307:臨時重定向,307 的定義實際上和 302 是一致的,唯一的區別在於,307 狀態碼不允許瀏覽器將原本為 POST 的請求重定向到 GET 請求上。
401 和 404 的區別
- 401 unauthorized,表示發送的請求需要有通過 HTTP 認證的認證信息
- 403 forbidden,表示對請求資源的訪問被服務器拒絕
打個生動的比方:
- 401:我去找個人,門衛說不認識我不讓我進
- 403:我去找個人,門衛說認識我,但是我不能進,因為我不配
