在最近的項目中,我發現不少人在設計 REST API 的時候,往往僅僅通過應用層的協議來返回調用的狀態,而忽略了 HTTP 狀態碼本身的含義。
本文參考 https://restfulapi.net/http-status-codes,我在這里做一個簡化版本,列出常見、但是往往會忽略使用的錯誤碼。
分類
分類 | 描述 |
---|---|
1xx: Informational | 用于協議握手階段的臨時應答 |
2xx: Success | 客戶端的請求被成功地接收 |
3xx: Redirection | 客戶端必須有一些附加的動作才能完成它們的請求 |
4xx: Client Error | 此類錯誤應該由客戶端負責 |
5xx: Server Error | 服務器對此類錯誤負責 |
201 Created
用于表明一個實體(Entity)被成功地創建了,例如: 創建訂單的 Endpoint POST /admin/orders
,在成功創建后應該返回 201 Created
。
202 Accepted
假如電商的結賬過程需要異步完成。例如: 結賬操作需要異步調用貨運公司的 API 才能知道運費信息。因此就需要一種異步的流程來處理。
首先,客戶端先創建了一個結賬(Checkout),POST /admin/checkouts
,新創建的 checkout
數據馬上會返回的,但是 shipping-rate
是空的。
HTTP/1.1 202 Accepted
Content-Type: application/json; charset=utf-8
Location: https://app.mystore.com/admin/checkouts/f9604c/
Retry-After: 1
{
checkout: {
"created_at":"2016-03-18T13:21:39-04:00",
...
"shipping_rate":null,
...
}
}
此時返回的狀態碼是 202 Accepted
,表示數據不完整,可以后續通過“拉”操作來完成。Location
給出的是后續的“拉” API 的 Endpoint。
Retry-After
給出了“拉”的時間間隔,有兩種格式。上例中單位為 “秒”,也可以跟一個期待來拉的日期時間,格式參見 HTTP Date。
連續“拉”的過程
當客戶端通過去拉:
GET /admin/checkouts/f9604c/ HTTP/1.1
Host: app.mystore.com
但是仍然沒有獲得運費信息,那么返回內容為:
HTTP/1.1 202 ACCEPTED
Content-Type: application/json; charset=utf-8
Location: https: https://app.mystore.com/admin/checkouts/f9604c
Retry-After: 1
{
"shipping_rates": []
}
如果某次“拉”發現運費信息已經得到,那么返回的狀態碼就是 200 Ok
:
HTTP/1.1 200 OK
Location: https: https://app.mystore.com/admin/checkouts/f9604c
Retry-After: 1
{
"shipping_rates": [
{
"price": 10.00,
"title": "Ground",
"phone_required": false,
"delivery_range": []
}
]
}
204 No Content
有時,PUT
,POST
或者 DELETE
操作沒有任何需要返回的數據,則可以直接用 204 No Content
,顯示地告訴客戶端沒有消息體。
303 See Other
303 See Other
可以被用于一個有趣的場景。例如,你需要一口氣建立一大批 checkouts。如果超過了 API 單位時間調用限制,那么則會返回 429 Too Many Requests
。但是還有一種可能是,即使沒有超過調用限制,但是系統也可能將你的請求放入隊列慢慢處理,此時,你就會收到 303 See Other
返回狀態,以及 Location
頭告訴調用者應該通過那個 URL 進行后續的輪訓,使用流程類似 202 Accepted
。
400 Bad Request
如果其他 4xx 的狀態碼不適合表示出錯原因,那么用 400 Bad Request
兜底。
401 Unauthorized
加入客戶端訪問某個訂單數據,但是沒有在 HTTP Header 中附帶 User Token,那么就應該返回這個錯誤碼。用來告訴客戶端,它想訪問的資源是需要先進行用戶認證才能完成。
402 Payment Required
如果訪問的資源超期需要續費,則返回 402 Payment Required
。例如: 用戶的店鋪超期未付費,那么訪問該店鋪所有相關的 API 都會返回這個狀態。
403 Forbidden
和 401 Unauthorized
不同,403 Forbidden
是在 User Token 存在,但是權限不足以獲取目標資源時返回。例如,你用 Alice 的 User Token 去訪問 Bob 的訂單。
404 Not Found
GET /admin/orders/{orderId}
,假如 orderId
對應的訂單不存在,那么我們應該顯示地返回 404 Not Found
作為狀態碼。
422 Unprocessable Entity (不能處理的實體)
一般發生在數據格式沒有問題,但是在數據的具體的“語義”驗證階段發現問題,則返回 422 Unprocessable Entity
。 例如: 我們要創建一個訂單,但是 channel
屬性填寫了一個未知的值。此時我們應該返回 422 Unprocessable Entity
作為 HTTP 的狀態碼,然后在消息體的 code
或者 error
字段提供更精準的信息。
423 Locked
如果被訪問的資源被“鎖”住,禁止修改和刪除,可以返回此狀態碼。典型的例子是,訂單在發貨后可以被鎖住,避免不小心修改。
429 Too Many Requests
這個很多人都熟悉了,用于單位時間內 API 訪問次數超限。
501 Not Implemented
這個狀態碼往往用于今后會提供這個 API Endpoint 的有效實現,但是目前還沒有,先占個坑。如果客戶端不小心調了,就會返回 501 Not Implemented
。