Skip to content
ADP
API Design PrincipleBETA

[ADP-403] 問題類型設計

TIP

2025.05.09 根據 RFC 9457,type 欄位必須足夠通用,但實務上有時需更細緻的子類型以利客戶端處理。經多方實作經驗,本規範明確建議:不應再設計 extraType 欄位,所有問題分類都應統一以 type URI 表示,避免多餘欄位造成混淆。

核心原則

  1. URI 參考:必須(MUST)是人類可讀的 URI reference。

TIP

在 RFC9457 中,僅有提到 type 必須是相對或絕對 uri。 但是,根據 RFC9457 中提到 title 欄位是在人類無法理解 type 欄位時用來補充說明這個前提下,以及各個 HTTP Problem 的實作,本規範設計者認為 type 必須被設計為 human readable 的 uri reference。

也許當有一天應用程式成長到某個程度時,問題類型列表過長會進入到一個無法維護的狀態,此時有可能會變成設計 type: https://api.example.com/problems/1234088abc 作為問題類型是可以接受的,但是必須(MUST)真實存在此 uri 可以被解析到。

雖然 /1234088abc 也是正確的 uri,但是在語意理解的角度下,我們認為應該避免使用這種 uri 作為問題類型。

  1. 相對 URI:當不確定問題發布位置或是否發布時,可(MAY)使用相對 URI reference。

  2. API 提供者應該(SHOULD)提供一個問題類型列表。

TIP

目前針對問題類型的設計可能會有疑慮:RFC9457 並未提供足夠的範例用以描述問題類型該如何設計,比如 究竟是:not-found 搭配 /books 作為 instance 還是 book-not-found 還是 book/not-found? 以及 /problems 是否應該作為問題類型的前綴。

本規範建議先在單一應用程式內選擇統一一種做法後,等待之後規範推廣更加深遠的情況下去做應用間的問題類型統合。

以下暫時提供一些範例:

  • /problems/not-found
  • /problems/user-not-found
  • /problems/out-of-organization
  • /problems/invalid-license

因為 RFC9457 明確指出可以設計特定於某問題類型的欄位,因此倘若想要針對同一問題類型設計多種子類型,可以

  1. 考慮使用 / 或者 - 來區分
  2. 使用特定於問題類型的擴充欄位
  1. 應該(SHOULD)盡可能地使用通用或已存在的問題類型。

  2. 如果確實需要其他資訊,可以針對問題類型(MAY)添加額外屬性(property)來擴展問題 JSON

    http
    {
      "type": "https://example.dev/problems/out-of-credit",
      "title": "您的請求無效。",
      "credit": 10,
      "remainingCredit": 0,
    }

設計流程

  1. 檢視現有的 HTTP 狀態碼,參考 ADP-200
  2. 如果語意符合,使用該 HTTP 狀態碼的 URI reference 轉換(如:/problems/not-found)。

TIP

根據 RFC9457 原始的定義,about:blank 作為問題類型是被推薦的,但是本規範設計者認為如果要以 type 作為問題類型索引,應該盡可能直接指出而不是先看到 about:blank 再去檢查 status 代表的語意。

  1. 如果語意不符合,應查閱預定義的問題類型列表。
  2. 如果沒有匹配的狀態,應提出新類型,確保它們足夠通用。
  3. 使用 detail 欄位提供修正錯誤的方法。
  4. 使用 errors 欄位描述多個錯誤。

[已廢止] 子類型(extraType)設計提案

注意:本節為歷史設計,現已明確不建議使用 extraType 欄位,請統一以 type URI 表示所有問題分類。

早期考慮到有時需更細緻的子類型,曾提出 extraType 欄位設計。實務上,建議將子類型直接納入 type URI,例如:https://apidoc.alive.dev/problems/not-found/user-not-found

  • 不再建議引入 extraType 欄位,請以 type URI 層級式設計分類。

    json
    {
      "type": "https://example.com/problems/authentication-error/user-not-found",
      "title": "Authentication Error",
      "status": 409,
      "detail": "Your session has expired due to JWT",
      "errors": []
    }

RFC 9457 合規指南

  1. 問題類型必須(MUST)是通用的,而非特定產品的。
  2. 應(SHOULD)最大化重用現有問題類型。
  3. 當 HTTP 狀態碼足夠時使用 about:blank。查閱ADP-402
  4. 查閱ADP-406 以取得更多類型的範例。

參考資料