HTTP 狀態碼

可檢索的 HTTP 狀態碼速查表,包含標準原因短語與定義它的 RFC 章節,支援按 1xx 至 5xx 分類過濾。

這個響應碼到底代表什麼? 輸入數字(如 429)或單詞(如 gateway)過濾表格,也可以只看某一類。每行給出狀態碼、在鏈路上實際傳輸的原因短語,以及定義它的規範章節。

匹配的狀態碼
狀態碼 原因短語 定義出處

正確理解 HTTP 狀態碼

首位數字才是真正的契約

每個 HTTP 響應都以三位數字開頭,而客戶端必須理解的只有第一位。RFC 9110 寫得很明確:收到無法識別的 499 時,客戶端應當完全按 400 處理。類別決定語義,後兩位只是細化。正是這條規則讓協議可以持續擴充套件——2005 年寫的代理今天仍能正確轉發 451,哪怕它根本不知道什麼是法律審查。

五個類別按"接下來誰負責"劃分得很乾淨:1xx 是臨時響應,真正的結果還在後面;2xx 表示成功,客戶端可以收工;3xx 交回一個重定向,客戶端應換個地址重試;4xx 歸咎於請求本身,原樣重發只會再次失敗;5xx 歸咎於服務端,同樣的請求重試有可能成功。所以重試邏輯應該按類別而不是具體碼來寫:重試 503 合理,重試 403 是 bug。

最容易混淆的幾組

301 與 308、302 與 307 的區別不是風格問題。舊的一組允許客戶端在跟隨重定向時把 POST 改寫成 GET,瀏覽器歷史上確實這麼做。新的一組禁止改寫,方法和請求體都會被保留。如果用 301 遷移一個表單端點,部分客戶端會靜默地把提交變成 GET 並丟掉負載。非冪等的請求請用 308 或 307。

401 和 403 同樣常被混用。401 表示請求未通過認證,響應必須帶上 WWW-Authenticate 挑戰頭,告訴客戶端該怎樣帶憑據重試;403 表示服務端已經知道你是誰,但仍然拒絕。不帶挑戰頭的 401 屬於違反規範,而使用者只是忘了登入卻返回 403,會讓排查變得困難得多。

4xx 裡還有一組很有用的劃分:400 與 422。400 表示請求根本無法解析,語法就是壞的;422 表示語法解析正常,但內容沒通過校驗。區分這兩者能把一個含糊的失敗變成可行動的提示。

原因短語只寫給人看

狀態碼旁邊的文字(如 Not FoundI'm a teapot)叫原因短語。HTTP/1.1 會在狀態行裡傳輸它,但 HTTP/2 和 HTTP/3 已徹底移除,所以現代連線上往往只有數字而沒有短語。客戶端程式碼絕不應該依據這個字串分支判斷——它存在的意義僅僅是讓人在看日誌或原始抓包時不用查表。

有些狀態碼的約束也比看上去更嚴格:204 和 304 不得攜帶訊息體,中介軟體擅自新增就會產生非法響應;HEAD 響應無論什麼碼都不帶訊息體。這些成幀規則很重要,因為不該有訊息體的地方出現訊息體會破壞連線複用的同步,表現出來是跨請求的詭異串資料,而不是一個明確的報錯。

開源說明:使用原生 JavaScript 實現,不依賴第三方庫。

常見問題

HTTP 狀態碼一共有多少個?
IANA 註冊的狀態碼在五個類別中略多於六十個,本表全部收錄,另外還補充了若干廣泛部署的 WebDAV 與擴充套件狀態碼。登錄檔是有意開放的,隨時可能新增,這也正是客戶端必須按首位數字兜底的原因。
永久重定向該用 301 還是 308?
除非你明確希望老客戶端把 POST 轉成 GET,否則用 308。兩者都表示資源已永久遷移,但只有 308 保證方法和請求體在重定向後保持不變。普通頁面搬遷兩者都可以,301 的老舊相容性稍好一些。
401 和 403 有什麼區別?
401 表示尚未認證,響應必須帶 WWW-Authenticate 頭說明如何認證;403 表示認證已通過但仍無許可權。使用者只是需要登入就返回 401,賬號確實缺少許可權才返回 403。
418 I'm a teapot 是真的狀態碼嗎?
從 RFC 2324 的角度說是真的,它定義於 1998 年的愚人節規範「超文本咖啡壺控制協議」。IANA 保留了 418,防止被其他用途佔用。它不屬於 HTTP 本體,但不少框架把它作為彩蛋實現了。
客戶端應該自動重試哪些狀態碼?
可以重試 408、429 以及大多數 5xx,並且只要響應帶了 Retry-After 就必須遵守。除 408 和 429 外的 4xx 不要重試,因為問題出在請求本身,原樣重發結果完全相同。
為什麼我的 HTTP/2 響應沒有原因短語?
HTTP/2 和 HTTP/3 從線路格式中移除了原因短語,因為本來就沒有客戶端應該去解析它,鏈路上只傳數字。工具為 HTTP/2 響應顯示的短語,都是在本地用類似本表的資料查出來的。