[ADP-401] HTTP 問題基礎
概述
錯誤回應是任何 API 的重要組成部分。顯然,HTTP 狀態碼對於錯誤(4xx,5xx)無法為 API 調用者提供足夠的資訊來準確理解發生了什麼。
過去我們可能會引入自定義錯誤代碼來描述標準 HTTP 狀態錯誤代碼以外的錯誤,但這並不清晰也不直觀。
目前 RFC 9457 提供了一種描述錯誤的標準方式,本 ADP 基於 RFC 9457 提供了一種設計錯誤回應的標準方法。
指導原則
錯誤回應必須(MUST)與 HTTP Problem 兼容。
錯誤回應必須(MUST)採用 JSON 格式。
錯誤回應的 Content-Type 標頭必須(MUST)為
application/problem+json
。應(SHOULD)盡可能重用現有的問題類型:
如果確實需要其他資訊,可以(MAY)添加額外屬性(property)來擴展問題 JSON
http{ "type": "https://example.net/validation-error", "title": "您的請求無效。", "extraInfo": "...." }
問題類型無法描述清楚的,可以考慮設計額外類型,參見 ADP-403。
錯誤回應結構
錯誤回應的範例:
HTTP/1.1 500 Internal Server Error
Content-Type: application/problem+json
{
type: '/problems/predefined-type',
status: 500,
title: '簡短的人類可讀錯誤描述',
instance: '/items/12345',
detail: '指引使用者如何修復問題'
}
錯誤回應的基本結構應如下:
屬性 | 描述 | 必需 | 示例 |
---|---|---|---|
type(string, uri-reference) | 必須是一個 URI(提示1) | 是 | /problems/{problem-type} |
title(string) | 問題類型的簡短、人類可讀摘要 | 是 | "Validation Error" |
status(integer) | 原始伺服器為此問題實例生成的 HTTP 狀態碼 | 是 | 400 |
detail(string) | 特定於此問題實例的人類可讀解釋(提示2) | 否 | "提供的輸入無效,請提供正確格式。" |
instance(string, uri-reference) | 標識問題特定實例的 URI 引用 | 否 | "/shop-items/123456" |
提示1
理想情況下,這應該指向一個真實的網站,以提供更多關於該類型的資訊,正如 RFC 建議的那樣。
如果我們在引入問題類型時無法提供絕對 URI,使用相對 URI 是可以接受的。如:/problems/invalid-input
提示2 關於 ProblemJSON.detail
- 如果其他屬性中已有足夠的資訊,
detail
可以(MAY)為空。 detail
應為用戶提供如何修復問題的指示。也就是說,它應該(SHOULD)使用口語化的英語(或如果您的 API 支持 Accept-Language,則使用其他語言),如 RFC9457 中定義的那樣。detail
和title
的區別:title
是一個更通用的問題簡短描述,而detail
提供了修復問題的具體指示。- 如果您的 API 支持 Accept-Language,
detail
可能是多語言的。無論您是否支持多語言,只要有detail
屬性(property),就應該(SHOULD)指定Content-Language
。
設計思路
許多網站使用自定義錯誤系統來描述 HTTP 狀態碼以外的自定義錯誤,例如額外的基於數字的代碼。然而,用戶仍然需要從互聯網查詢代碼的含義,因為不同應用程序之間沒有標準。
示例
讓我們以 Windows 錯誤代碼為例。參見 https://learn.microsoft.com/zh-tw/windows-hardware/drivers/debugger/bug-check-code-reference2。
應該這樣做
{
"type": "/problems/ipt-watchdog-timeout",
"status": 500,
"detail": "...."
}
不應該這樣做
{
"status": "0x0001db"
}