不背整張表,只記三個問題 —— 寫給每次都在猶豫「回 400 還是 422」的人
狀態碼是回應的第一行摘要,寫給不會讀 body 的人看的。
誰不讀 body?瀏覽器、CDN/快取、SDK 的自動重試、你的監控告警、負載平衡器。它們只看那三個數字就決定要不要重送、要不要快取、要不要把你叫醒。
想像一間餐廳,不管你點的菜有沒有做出來,服務生都笑著說「好的沒問題」,然後在收據角落用小字寫「其實廚房失火了」。
這就是「全部回 200,錯誤寫在 body 裡」的 API。後果不是理論上的:
狀態碼給機器看,body 給人看。兩個都要,但別把機器要的那份藏在 body 裡。
五個家族只是開胃菜(1xx 還在處理、2xx 成功、3xx 換個地方拿、4xx 請求有問題、5xx 伺服器有問題)。真正每天在用的是這條線:
這條線不只是語意潔癖 —— 它決定了誰的告警會響、重試機制會不會自動重送、SLA 的錯誤率算在誰頭上。把自己的 bug 回成 400,等於把自己的鍋丟給呼叫方;反過來把參數錯回成 500,你會被自己的告警半夜叫醒去看一個根本沒壞的服務。
101 是升級成 WebSocket 時用的)。3xx 是「東西不在這,去那邊拿」:301/308 永久搬家、302/307 暫時的、304 Not Modified 是快取專用(配 ETag/If-None-Match,代表「你手上那份還新鮮,我不用再傳一次」)。分類定義見 RFC 9110 §15。設計時不要從「有哪些碼」開始想,那是查表。從三個問題開始問,答完就只剩兩三個候選:
手上這個回應該回什麼?照著 ①②③ 問一輪,答案自己會浮出來
200 OK。201 Created,順手在 Location 標頭放新資源的網址。202 Accepted,回一個可以查進度的位置。204 No Content,body 必須是空的。
400 和 500,但也不必用滿。挑一組你團隊講得清楚的常用碼(下面那張表就夠用),寫進規範,全站一致 —— 一致比精準更值錢。400/500)就好,然後把細節寫在 body。
| 碼 | 白話 | 什麼時候回 |
|---|---|---|
| 200 OK | 好了,東西在這 | 查詢成功、更新成功且要回內容 |
| 201 Created | 幫你建好了 | 新增資源成功;附上 Location |
| 202 Accepted | 收下了,還在做 | 非同步任務、排入佇列 |
| 204 No Content | 做完了,沒東西回 | 刪除成功、無回傳的更新 |
| 400 Bad Request | 你這包我讀不懂 | JSON 壞掉、少必填、型別錯、格式不合 |
| 401 Unauthorized | 你是誰? | 沒帶憑證或憑證過期/無效。要附 WWW-Authenticate |
| 403 Forbidden | 知道你是誰,但不行 | 身分沒問題,就是沒這個權限 |
| 404 Not Found | 沒這東西 | 路徑不存在、ID 查無資料 |
| 405 Method Not Allowed | 路徑對,動詞錯 | 對只讀端點送 DELETE。要附 Allow 列出可用方法 |
| 409 Conflict | 跟目前狀態打架 | 重複註冊、樂觀鎖版本衝突、狀態機不允許的轉換 |
| 415 Unsupported Media Type | 這格式我不吃 | 送了 XML 但我只收 JSON |
| 422 Unprocessable Content | 看得懂,但不合理 | 格式完全正確,是商業規則不通過(生日在未來、金額超上限) |
| 429 Too Many Requests | 太快了,慢點 | 觸發限流。附 Retry-After 告訴對方等多久 |
| 500 Internal Server Error | 我壞了,還不知道為什麼 | 沒接住的例外。別把細節或堆疊吐給外面 |
| 502 Bad Gateway | 我後面那台回了垃圾 | 上游回了無效回應/連不上 |
| 503 Service Unavailable | 暫時不能服務 | 維護中、過載、熔斷開啟。附 Retry-After |
| 504 Gateway Timeout | 我後面那台太慢 | 等上游等到超時 |
標色的那幾條是八成情況會用到的;其餘先知道存在,用到再查。
application/problem+json,欄位如 type/title/detail/instance),照它做,前端和第三方接起來都省事。301/302 會把 POST 悄悄改成 GET 再送一次(body 就沒了)。307/308 是後來補的,明確規定方法和 body 都要原封不動。所以:需要保留方法 → 用 307(暫時)/308(永久)。另外 301/308 會被瀏覽器長期記住,改錯了很難收回,搬家沒搬乾淨前先用暫時的那組。心裡先答,再往下想理由(沒有標準答案警察,但每題都有明顯較好的選擇):
204(做完了、沒 body)。2. 202 + 一個查進度的位置(別回 200 假裝做完了)。3. 409(跟現況衝突)——若你把「email 重複」當成欄位驗證失敗,回 400/422 也說得通,重點是全站一致。4. 401(是「你是誰」的問題,不是權限問題)。5. 504(上游超時),不是 500——分清楚,你才會去查金流商而不是查自己。面對任何一個回應,你能三秒內說出該回哪個碼、而且講得出理由;並且在 4xx/5xx 之間不會擺錯邊。
你不需要背得出 418 是什麼(真的有這個碼,是愚人節玩笑的茶壺)。你需要的是:挑一組常用碼、寫進團隊規範、全站用一樣的規則。
先問「是誰的錯」,再問「等一下會不會好」——
剩下的就只是查表。
429 出自 RFC 6585,不在 9110 裡)。*「三個問題」的挑碼流程是本文為了好記自行整理的教學框架,非引自單一來源;每個碼的語意定義則依 RFC 9110 / IANA。