| RFC 9457 | HTTP APIのための問題詳細 | 2023年7月 |
| Nottingham, et al. | 標準化過程 | [Page] |
この文書は、HTTP APIのために新しいエラーレスポンス形式を定義する必要を避けるため、HTTPレスポンス内容でエラーの機械可読な詳細を伝達する「問題詳細」を定義します。¶
この文書はRFC 7807を廃止します。¶
これはインターネット標準化過程の文書です。¶
この文書は、インターネット技術タスクフォース (IETF)の成果物です。これはIETFコミュニティの合意を表します。これは 公開レビューを受けており、Internet Engineering Steering Group (IESG)によって公開が承認されています。インターネット標準に関する さらなる情報は、RFC 7841のセクション2で入手できます。¶
この文書の現在の状態、正誤表、および この文書に関するフィードバックの提供方法についての情報は、 https://www.rfc-editor.org/info/rfc9457で入手できます。¶
Copyright (c) 2023 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.¶
HTTPステータスコード([HTTP]のセクション15)は、 エラーについて有用であるのに十分な情報を常に伝達できるとは限りません。Webブラウザーを使用する人間は、多くの場合、 HTML [HTML5] レスポンス内容を理解できますが、 HTTP APIの非人間の利用者がそうするのは困難です。¶
その欠点に対処するために、この仕様は、遭遇した問題の詳細――「問題詳細」――を記述するための 単純なJSON [JSON] および XML [XML] 文書形式を定義します。¶
たとえば、クライアントのアカウントに十分なクレジットがないことを示すレスポンスを考えます。 APIの設計者は、汎用HTTPソフトウェア(クライアントライブラリ、キャッシュ、プロキシなど)にレスポンスの一般的な意味を通知するために、 403 Forbiddenステータスコードを使用することを決定するかもしれません。 API固有の問題詳細(サーバーがリクエストを拒否した理由や該当するアカウント残高など)は、 クライアントがそれらに適切に対処できるように(たとえば、アカウントへの追加クレジットの移転をトリガーするなど)、 レスポンス内容で伝達できます。¶
この仕様は、特定の「問題型」(例:「クレジット不足」)を URI [URI]で識別します。HTTP APIは、 自身に固有の問題を識別するために自身の管理下にあるURIを使用できます。または、相互運用性を促進し、 共通の意味を活用するために既存のものを再利用できます(セクション4.2を参照)。¶
問題詳細には、問題の特定の発生を識別するURIなど、他の情報を含めることができます (実質的に「先週の木曜日にJoeに十分なクレジットがなかった時」という概念に識別子を与えるものです)。これはサポートや フォレンジックの目的に役立つことがあります。¶
問題詳細のデータモデルはJSON [JSON]オブジェクトです。JSON文書としてシリアライズされる場合、 これは"application/problem+json"メディア型を使用します。付録Bは、 "application/problem+xml"メディア型を使用する同等のXML形式を定義します。¶
問題詳細がHTTPレスポンスで伝達される場合、その内容はプロアクティブネゴシエーションを使用して ネゴシエートできます。[HTTP]のセクション12.1を参照してください。特に、 人間可読な文字列(titleやdescription内のものなど)で使用される言語は、 Accept-Languageリクエストヘッダーフィールド([HTTP]のセクション12.5.4)を使用して ネゴシエートできますが、そのネゴシエーションによっても、優先されないデフォルト表現が返されることがあります。¶
問題詳細は任意のHTTPステータスコードで使用できますが、4xxおよび5xxレスポンスの意味に最も自然に適合します。 問題詳細は、HTTPで問題の詳細を伝達する唯一の方法では(当然ながら)ないことに注意してください。 たとえば、レスポンスが依然としてリソースの表現である場合、そのアプリケーションの形式で関連する詳細を記述することが しばしば望ましいです。同様に、定義済みのHTTPステータスコードは、追加の詳細を伝達する必要なしに多くの状況をカバーします。¶
この仕様の目的は、共通のエラー形式を必要とするアプリケーションのためにそれを定義し、 アプリケーションが独自のものを定義する必要がないようにすること、またはさらに悪いことに、 既存のHTTPステータスコードの意味を再定義しようと誘惑されないようにすることです。アプリケーションがエラーを伝達するためにこれを使用しないことを選択した場合でも、 その設計を検討することは、既存形式でエラーを伝達するときに直面する設計上の判断を導くのに役立ちます。¶
この文書におけるキーワード「MUST」、「MUST NOT」、 「REQUIRED」、「SHALL」、「SHALL NOT」、「SHOULD」、「SHOULD NOT」、 「RECOMMENDED」、「NOT RECOMMENDED」、 「MAY」、および「OPTIONAL」は、 ここに示すようにすべて大文字で現れる場合に限り、 BCP 14 [RFC2119] [RFC8174]で説明されているように解釈されます。¶
問題詳細の正規モデルはJSON [JSON]オブジェクトです。JSON文書でシリアライズされる場合、 その形式は"application/problem+json"メディア型で識別されます。¶
例:¶
ここでは、(そのtypeによって識別される)クレジット不足の問題が、 "title"で403の理由を示し、"instance"で特定の問題発生を識別し、 "detail"で発生固有の詳細を与え、さらに2つの拡張を追加しています。"balance"はアカウントの残高を伝達し、 "accounts"はアカウントにチャージできるリンクを一覧表示します。¶
それを受け入れるように設計されている場合、問題固有の拡張は同じ問題型の複数のインスタンスを伝達できます。 例:¶
ここでの架空の問題型は"errors"拡張を定義します。これは各検証エラーの詳細を記述する配列です。 各メンバーは、問題を記述する"detail"と、JSON Pointer [JSON-POINTER]を使用してリクエスト内容内の問題の位置を示す "pointer"を含むオブジェクトです。¶
APIが同じ型を共有しない複数の問題に遭遇した場合、最も関連性が高い、または緊急度の高い問題を レスポンスで表現することがRECOMMENDEDです。複数の異なる型を伝達する汎用的な「バッチ」問題型を作成することは可能ですが、 それらはHTTPの意味にうまく対応しません。¶
また、クライアントがAcceptでそれを列挙していなかったにもかかわらず、APIが "application/problem+json"型で応答していることにも注意してください。これはHTTPで許可されています ([HTTP]のセクション12.5.1を参照)。¶
問題詳細オブジェクトは次のメンバーを持つことができます。メンバーの値の型が指定された型と一致しない場合、 そのメンバーはMUST無視されます。すなわち、そのメンバーが存在しなかったかのように処理は継続します。¶
"type"メンバーは、問題型を識別するURI参照 [URI]を含むJSON文字列です。 利用者は、(必要に応じて解決した後の)"type" URIを問題型の主要な識別子として MUST使用します。¶
このメンバーが存在しない場合、その値は"about:blank"であると見なされます。¶
type URIがロケーターである場合(たとえば、"http"または"https"スキームを持つもの)、 それを逆参照すると、問題型に関する人間可読な文書(たとえばHTML [HTML5]を使用したもの)を提供 SHOULDします。ただし、利用者は、開発者に情報を提供するとき(たとえばデバッグツールが使用中の場合など)を除き、 type URIを自動的に逆参照SHOULD NOTしません。¶
"type"が相対URIを含む場合、それは[URI]のセクション 5に従って、文書の基底URIを基準に解決されます。ただし、 相対URIの使用は混乱を招く可能性があり、すべての実装で正しく処理されない可能性があります。¶
たとえば、2つのリソース "https://api.example.org/foo/bar/123"と"https://api.example.org/widget/456"の両方が 相対URI参照"example-problem"と等しい"type"で応答する場合、 解決後にはそれぞれ異なるリソース ("https://api.example.org/foo/bar/example-problem"と "https://api.example.org/widget/example-problem")を識別します。その結果、 可能な場合は"type"で絶対URIを使用し、相対URIを使用する場合は完全なパス(例: "/types/123")を含めることがRECOMMENDEDです。¶
type URIは解決不能なURIであることが許可されています。たとえば、 tag URIスキーム [TAG] は、 問題型を一意に識別するために使用できます。¶
tag:example@example.org,2021-09-17:OutOfLuck¶
しかし、将来URIを解決することが望ましくなる可能性があるため、 この仕様では解決可能なtype URIが推奨されます。たとえば、API設計者が上記のURIを使用し、 後でエラーに関する情報を発見するためにtype URIを解決するツールを採用した場合、その機能を活用するには 解決可能なURIへ切り替える必要があり、問題型に新しい識別性を作成して破壊的変更を導入することになります。¶
"status"メンバーは、この問題の発生についてオリジンサーバーによって生成された HTTPステータスコード([HTTP]のセクション 15)を示すJSON数値です。¶
"status"メンバーは、存在する場合でも助言的なものにすぎません。これは利用者の便宜のために使用された HTTPステータスコードを伝達します。生成者は、この形式を理解しない汎用HTTPソフトウェアがなお正しく振る舞うことを保証するため、 実際のHTTPレスポンスで同じステータスコードをMUST使用します。 その使用に関する追加の注意については、セクション 5を参照してください。¶
利用者は、(たとえば仲介者またはキャッシュによって)ステータスコードが変更された場合や、 メッセージの内容がHTTP情報なしで永続化された場合に、生成者が使用した元のステータスコードを判断するために statusメンバーを使用できます。汎用HTTPソフトウェアは引き続きHTTPステータスコードを使用します。¶
"title"メンバーは、問題型の短く人間可読な要約を含むJSON文字列です。¶
これは、ローカライズ(たとえばプロアクティブコンテンツネゴシエーションの使用。 [HTTP]のセクション12.1を参照)を除き、 問題の発生ごとに変化SHOULD NOTしません。¶
"title"文字列は助言的なものであり、type URIの意味を知らず、かつ発見できない利用者 (たとえばオフラインログ分析時)のためだけに含まれます。¶
"detail"メンバーは、この問題の発生に固有の人間可読な説明を含むJSON文字列です。¶
"detail"文字列が存在する場合、それはデバッグ情報を提供するよりも、 クライアントが問題を修正するのを助けることに焦点を当てるべきです。¶
利用者は、情報を得るために"detail"メンバーを解析SHOULD NOTしません。 拡張の方がそのような情報を取得するのにより適しており、誤りが少ない方法です。¶
"instance"メンバーは、問題の特定の発生を識別するURI参照を含むJSON文字列です。¶
"instance" URIが逆参照可能である場合、そこから問題詳細オブジェクトを取得できます。 また、プロアクティブコンテンツネゴシエーション([HTTP]のセクション12.5.1を参照)の使用を通じて、 他の形式で問題発生に関する情報を返すこともあります。¶
"instance" URIが逆参照可能でない場合、それはサーバーにとって重要である可能性があるが クライアントにとっては不透明な、問題発生の一意な識別子として機能します。¶
"instance"が相対URIを含む場合、それは[URI]のセクション 5に従って、文書の基底URIを基準に解決されます。ただし、 相対URIの使用は混乱を招く可能性があり、すべての実装で正しく処理されない可能性があります。¶
たとえば、2つのリソース "https://api.example.org/foo/bar/123"と"https://api.example.org/widget/456"の両方が 相対URI参照"example-instance"と等しい"instance"で応答する場合、解決後にはそれぞれ異なるリソース ("https://api.example.org/foo/bar/example-instance"と "https://api.example.org/widget/example-instance")を識別します。その結果、 可能な場合は"instance"で絶対URIを使用し、相対URIを使用する場合は完全なパス(例: "/instances/123")を含めることがRECOMMENDEDです。¶
問題型定義は、その問題型に固有の追加メンバーで問題詳細オブジェクトを拡張 MAYできます。¶
たとえば、上記のクレジット不足問題は、追加の問題固有情報を伝達するために、 "balance"と"accounts"という2つの拡張を定義しています。¶
同様に、「validation error」の例は、見つかった個々のエラー発生の一覧を含む "errors"拡張を定義しており、それぞれに詳細と位置へのポインターがあります。¶
問題詳細を利用するクライアントは、認識しないそのような拡張をすべて MUST無視します。これにより、問題型が進化し、将来的に追加情報を含めることが可能になります。¶
拡張を作成する際、問題型の著者は名前を慎重に選択すべきです。 XML形式(付録Bを参照)で使用するには、 それらは[XML]のセクション 2.3にあるName規則に適合する必要があります。¶
HTTP APIがエラー状態を示すレスポンスを定義する必要がある場合、新しい問題型を定義することが 適切であるかもしれません。¶
そうする前に、それらが何に適しており、何を他の仕組みに任せる方がよいかを理解することが重要です。¶
問題詳細は基盤実装のためのデバッグツールではありません。むしろ、HTTPインターフェイス自体について より詳しい詳細を公開する方法です。新しい問題型の設計者は、 セキュリティ上の考慮事項 (セクション5)、 特に、エラーメッセージを通じて実装内部を公開することで攻撃ベクトルを露出するリスクを慎重に考慮する必要があります。¶
同様に、真に汎用的な問題――すなわち、Web上の任意のリソースに適用されうる条件――は、 通常、単純なステータスコードとして表現する方がよいです。たとえば、PUTリクエストに対する403 Forbiddenステータスコードは 自明であるため、「書き込みアクセスが許可されていない」問題はおそらく不要です。¶
最後に、アプリケーションには、すでに定義している形式でエラーを伝達する、より適切な方法があるかもしれません。 問題詳細は、新しい「fault」または「error」文書形式を確立する必要性を避けることを意図しており、 既存のドメイン固有形式を置き換えることを意図していません。¶
とはいえ、HTTPコンテンツネゴシエーションを使用して既存のHTTP APIに問題詳細のサポートを追加することは可能です (たとえば、この形式への優先を示すためにAcceptリクエストヘッダーを使用するなど。 [HTTP]のセクション 12.5.1を参照)。¶
新しい問題型定義は、次を文書化MUSTします。¶
問題型定義は、適切な状況でRetry-Afterレスポンスヘッダー ([HTTP]のセクション 10.2.3)の使用を指定MAYできます。¶
問題型URIは、問題を解決する方法を説明するHTML [HTML5]文書に解決 SHOULDします。¶
問題型定義は、問題詳細オブジェクト上の追加メンバーを指定 MAYできます。 たとえば、拡張は、機械が問題を解決するために使用できる別のリソースへの型付きリンク [WEB-LINKING]を使用するかもしれません。¶
そのような追加メンバーが定義される場合、その名前は文字(ALPHA、[ABNF]の付録 B.1に従う)で始まる SHOULDであり、ALPHA、DIGIT ([ABNF]の付録 B.1)および"_"の文字で構成される SHOULDであり(JSON以外の形式でもシリアライズできるようにするため)、 3文字以上であるSHOULDです。¶
たとえば、オンラインショッピングカートにHTTP APIを公開している場合、 ユーザーがクレジット不足(上記の例)であるため購入できないことを示す必要があるかもしれません。¶
この情報を収容できるアプリケーション固有の形式がすでにある場合、おそらくそれを行うのが最善です。 しかし、ない場合は、問題詳細形式のいずれか――APIがJSONベースならJSON、その形式を使用するならXML――を使用するかもしれません。¶
そうするために、レジストリ(セクション4.2)で目的に合った既定義のtype URIを探すかもしれません。 利用可能なものがあれば、そのURIを再利用できます。¶
利用可能なものがなければ、(自身の管理下にあり、時間が経っても安定しているべき) 新しいtype URI、適切なtitle、およびそれとともに使用されるHTTPステータスコードを作成して文書化し、 それが何を意味し、どのように扱われるべきかを併せて示すことができます。¶
この仕様は、再利用を促進するために、共通で広く使用される問題型URIのための "HTTP Problem Types"レジストリを定義します。¶
このレジストリのポリシーは、[RFC8126]のセクション 4.6に従うSpecification Requiredです。¶
リクエストを評価する際、指定専門家は、コミュニティからのフィードバック、問題型がどれほど明確に定義されているか、 およびこの仕様の要件を考慮すべきです。 ベンダー固有、アプリケーション固有、および展開固有の値は登録できません。 仕様文書は安定した自由に利用可能な方法で公開されるべきです(理想的にはURLの場所に置かれる)が、標準である必要はありません。¶
登録は、type URIに接頭辞「https://iana.org/assignments/http-problem-types#」 を使用MAYできます。それらのURIは解決できない可能性があることに注意してください。¶
登録リクエストには、次のテンプレートを使用すべきです。¶
登録リクエストの送付先の詳細については、 <https://iana.org/assignments/http-problem-types> のレジストリを参照してください。¶
この仕様は、1つのProblem Typeである"about:blank"を次のように登録します。¶
"about:blank" URI [ABOUT]は、問題型として使用される場合、 その問題がHTTPステータスコードの意味を超える追加の意味を持たないことを示します。¶
"about:blank"が使用される場合、titleはそのコードに対して推奨されるHTTPステータス句と同じである SHOULDです(例: 404の場合は"Not Found"など)。ただし、 クライアントの優先(Accept-Languageリクエストヘッダーで表される)に合わせてローカライズ MAYされます。¶
"type"メンバーの定義方法(セクション3.1)によれば、"about:blank" URIは そのメンバーのデフォルト値であることに注意してください。したがって、明示的な"type"メンバーを持たない 任意の問題詳細オブジェクトは、暗黙的にこのURIを使用します。¶
新しい問題型を定義する際、含められる情報は慎重に検証されなければなりません。 同様に、実際に問題を生成する際には――どのようにシリアライズされるかにかかわらず――与えられる詳細も精査されなければなりません。¶
リスクには、システム、システムへのアクセス、またはシステムのユーザーのプライバシーを侵害するために悪用されうる情報の漏えいが含まれます。¶
発生情報へのリンクを提供する生成者は、スタックダンプのような実装詳細をHTTPインターフェイスを通じて利用可能にしないことが推奨されます。 これはサーバー実装、そのデータなどの機微な詳細を露出する可能性があるためです。¶
"status"メンバーはHTTPステータスコード自体で利用可能な情報を重複させ、 両者の不一致の可能性を生じさせます。不一致が、たとえば仲介者が転送中にHTTPステータスコードを変更したこと (プロキシやキャッシュなどによって)を示している可能性があるため、両者の相対的な優先順位は明確ではありません。 汎用HTTPソフトウェア(プロキシ、ロードバランサー、ファイアウォール、ウイルススキャナーなど)は、 このメンバーで伝達されるステータスコードを知っている、または尊重する可能性が低いです。¶
IANAは、"Media Types"レジストリ配下の"application"レジストリにおいて、 "application/problem+json"および"application/problem+xml"の登録をこの文書を参照するよう更新しました。¶
IANAは、セクション4.2で規定される"HTTP Problem Types"レジストリを作成し、 セクション4.2.1に従って"about:blank"を登録しました。¶
このセクションは、HTTP問題詳細のための非規範的なJSON Schema [JSON-SCHEMA]を示します。 これと仕様本文の間に不一致がある場合、後者が優先します。¶
# NOTE: '\' line wrapping per RFC 8792
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "An RFC 7807 problem object",
"type": "object",
"properties": {
"type": {
"type": "string",
"format": "uri-reference",
"description": "A URI reference that identifies the \
problem type."
},
"title": {
"type": "string",
"description": "A short, human-readable summary of the \
problem type."
},
"status": {
"type": "integer",
"description": "The HTTP status code \
generated by the origin server for this occurrence of the problem.",
"minimum": 100,
"maximum": 599
},
"detail": {
"type": "string",
"description": "A human-readable explanation specific to \
this occurrence of the problem."
},
"instance": {
"type": "string",
"format": "uri-reference",
"description": "A URI reference that identifies the \
specific occurrence of the problem. It may or may not yield \
further information if dereferenced."
}
}
}
¶
XML [XML]を使用するHTTPベースのAPIは、 この付録で定義される形式を使用して問題詳細を表現できます。¶
XML形式のためのRELAX NGスキーマ [ISO-19757-2] は次のとおりです。¶
default namespace ns = "urn:ietf:rfc:7807"
start = problem
problem =
element problem {
( element type { xsd:anyURI }?
& element title { xsd:string }?
& element detail { xsd:string }?
& element status { xsd:positiveInteger }?
& element instance { xsd:anyURI }? ),
anyNsElement
}
anyNsElement =
( element ns:* { anyNsElement | text }
| attribute * { text })*
¶
このスキーマは文書化のみを意図しており、XML形式のすべての制約を捉える規範的スキーマではないことに注意してください。 選択したスキーマ言語の機能に応じて、他のXMLスキーマ言語を使用して同様の制約の集合を定義することが可能です。¶
この形式のメディア型は"application/problem+xml"です。¶
拡張の配列およびオブジェクトは、1つ以上の子を含む要素をオブジェクトとして表すものと見なすことで、 XML形式へシリアライズされます。ただし、"i"という名前の子要素のみを1つ以上含む要素は、配列と見なされます。 たとえば、上記の例はXMLでは次のように表されます。¶
この形式はXML名前空間を使用します。これは主に、他のXMLベース形式へ埋め込むことを可能にするためであり、 他の名前空間の要素または属性で拡張できる、または拡張すべきであることを意味しません。 RELAX NGスキーマは、XML形式で使用される1つの名前空間からの要素のみを明示的に許可します。 すべての拡張配列およびオブジェクトは、その名前空間のみを使用してXMLマークアップに MUSTシリアライズされます。¶
XML形式を使用する場合、参照されるXSL Transformations(XSLT)コード [XSLT]を使用してXMLを変換するようクライアントに指示するXML処理命令を、 XMLに埋め込むことが可能です。このコードがXMLを(X)HTMLへ変換する場合、XML形式を提供しつつ、 変換を実行できるクライアントに、人間にわかりやすい(X)HTMLをレンダリングして表示させることが可能です。 この方法を使用する場合、XSLTコードを実行できるクライアントの数を最大化するために、XSLT 1.0を使用することが望ましいことに注意してください。¶
場合によっては、ここで説明されている形式以外の形式に問題詳細を埋め込むことが有利なことがあります。 たとえば、HTML [HTML5]を使用するAPIは、 その問題詳細を表現するためにもHTMLを使用したいかもしれません。¶
問題詳細は、既存のシリアライゼーション(JSONまたはXML)のいずれかをその形式にカプセル化するか、 問題詳細のモデル(セクション3で規定)を その形式の慣例へ変換することによって、他の形式に埋め込むことができます。¶
たとえば、HTMLでは、scriptタグ内にJSONをカプセル化することで問題を埋め込むことができます。¶
<script type="application/problem+json">
{
"type": "https://example.com/probs/out-of-credit",
"title": "You do not have enough credit.",
"detail": "Your current balance is 30, but that costs 50.",
"instance": "/account/12345/msgs/abc",
"balance": 30,
"accounts": ["/account/12345",
"/account/67890"]
}
</script>
¶
または、Resource Description Framework in Attributes(RDFa)[RDFA]へのマッピングを定義することもできます。¶
この仕様は、問題詳細を他の形式に埋め込むことについて具体的な推奨を行いません。 それらを埋め込む適切な方法は、使用される形式と、その形式の適用の両方に依存します。¶
この改訂では次の変更が行われました。¶