PR

[備忘録]REST APIのエラーレスポンス、RFC 9457に標準形式があるって知ってた?

はじめに

こんにちは、nobushiueshiです。

REST APIを自作したことがある方なら、一度はこんな悩みを抱えたことがあるのではないでしょうか。

「エラーが起きたとき、レスポンスのJSON、どんな形式で返せばいいんだろう?」

たとえば、こんなふうに悩みます。

// これでいいの?
{ "error": "Not Found" }

// それともこっち?
{ "message": "リソースが見つかりません", "code": 404 }

// いや、もっと詳細にすべき?
{ "status": 404, "detail": "指定されたユーザーは存在しません" }

チームや個人プロジェクトによってバラバラになりがちなこの問題、実は RFCで標準が定められている ことを最近知りました。今回はそれを調べてみたので、まとめて紹介します。

RFC 9457 とは?

RFC 9457「Problem Details for HTTP APIs」 というドキュメントがあります。

これはHTTP APIがエラーを返すときの、JSONレスポンスの標準形式を定めたものです。以前は RFC 7807 として定義されていましたが、2023年に RFC 9457 として改訂・更新されています。

Content-Type は以下を使います。

application/problem+json

これ自体はまだ広く普及しているとは言いがたいですが、「標準仕様がある」という事実を知っているだけでも、API設計の議論がしやすくなります。

フィールドの定義

RFC 9457 では、以下のフィールドが定義されています。

フィールド必須説明
type任意エラーの種類を示すURI。ドキュメントへのリンクにもできる
title任意エラーの短い人間向けの説明(英語が想定)
status任意HTTPステータスコード(数値)
detail任意エラーの詳細説明。人間向けのメッセージ
instance任意エラーが発生した具体的なリソースのURI

すべて任意ですが、typedetail あたりは入れておくと親切です。

また、これらに加えて独自のフィールドを自由に追加できるのも大きなポイントです。

サンプル:よくあるエラーケース

404 Not Found

HTTP/1.1 404 Not Found
Content-Type: application/problem+json

{
  "type": "https://example.com/errors/user-not-found",
  "title": "User Not Found",
  "status": 404,
  "detail": "指定されたID '42' のユーザーは存在しません。",
  "instance": "/users/42"
}

400 Bad Request(バリデーションエラー)

バリデーションエラーのように複数のエラーをまとめて返したい場合は、独自フィールドを追加して対応できます。

HTTP/1.1 400 Bad Request
Content-Type: application/problem+json

{
  "type": "https://example.com/errors/validation-error",
  "title": "Validation Error",
  "status": 400,
  "detail": "リクエストのパラメータに不正な値が含まれています。",
  "instance": "/users",
  "errors": [
    {
      "field": "email",
      "message": "メールアドレスの形式が正しくありません。"
    },
    {
      "field": "age",
      "message": "年齢は0以上の整数である必要があります。"
    }
  ]
}

401 Unauthorized

HTTP/1.1 401 Unauthorized
Content-Type: application/problem+json

{
  "type": "https://example.com/errors/unauthorized",
  "title": "Unauthorized",
  "status": 401,
  "detail": "このリソースへのアクセスには認証が必要です。",
  "instance": "/admin/settings"
}

500 Internal Server Error

HTTP/1.1 500 Internal Server Error
Content-Type: application/problem+json

{
  "type": "https://example.com/errors/internal-server-error",
  "title": "Internal Server Error",
  "status": 500,
  "detail": "サーバー内部でエラーが発生しました。時間をおいて再度お試しください。"
}

ポイントまとめ

  • type には エラーの種類を一意に識別するURI を入れる(実際にアクセスできるドキュメントURLにするのが理想)
  • detailユーザーや開発者が原因を理解できる文章 にする
  • instanceどのリソースでエラーが起きたか を示すために便利
  • 独自フィールド(errors など)を追加して柔軟に拡張できる
  • Content-Type は application/problem+json を使う

感想

正直、今まで「エラーのフォーマットなんて自分で決めればいいか」と思っていましたが、標準仕様があると知ってからは意識が変わりました。

特にチーム開発や、外部に公開するAPIを作る場合は、こういった標準に則っておくと「なぜこの形式なの?」という議論が不要になってスムーズです。個人開発でも、最初から標準形式に慣れておくと後々ラクになりますよ。

REST APIを作る機会がある方は、ぜひ RFC 9457 を意識してみてください!

参考

コメント

タイトルとURLをコピーしました