RFC7807に沿ったエラーレスポンスの実践について
トリプル・ダブリュー・ジャパン株式会社でソフトウェアアーキテクトをしています西田です。ネット上では主にkbigwheelの名前で活動しています。
今回は最近私達のチームで行ったRFC7807に沿ったエラーレスポンスの実践について紹介します。
RFC7807とは
2016年にIETFから発行された、新しいHTTP APIのエラーレスポンス形式*1です。 日本語の解説記事は非常に少ないですが、こちらのブログで非常にわかりやすく要所を日本語に翻訳しつつ説明されています。
この標準に沿うことで新しい開発メンバーへ仕様を共有することが簡単になります。 また過去にこの仕様を見たことがあれば、新たに勉強することは最小限で済みます。
サーバサイドチームの取り組み
私が所属するサーバサイドチームでは11月にAPIサービスの大幅なバージョンアップを行いました。 しかし、エラーレスポンスの仕様(特にレスポンスボディの仕様)が曖昧なままでアプリチームがハンドリングしたい粒度でエラー原因を返せていませんでした。 そこでエラーケースを再定義するとともにアプリがハンドリングするために必要十分な情報を持たせるよう改修を行うことになったのですが、どうせエラーレスポンス仕様を変更するならより標準的なフォーマットに寄せたいと考えた結果採用したのがRFC7807です。
仕様定義
RFC7807が定義する仕様にはいくつかの選択肢があります。 レスポンスフォーマットをJSONとXMLのどちらにするか、いくつかあるプロパティのうちどれを利用するか、などです。 それらについて私達のサービスではどれを使用するかを決めてgithub wiki上のページへ以下のようにまとめました(実際のエラーコード・URLとは変更しています)。
上に書かれていますが基本的に以下のように仕様を定めました。
ヘッダ
- Content-Type: application/problem+json
プロパティ
- type, titleのみを利用する。 またそれらのプロパティは必須であり、レスポンスによって特定のプロパティが欠けるようなことはない。
サンプル
HTTP/1.1 400 Bad Request Content-Type: application/problem+json { "type": "/api/v5/errors/invalid-device-id", "title": "Invalid deviceId." }
HTTP/1.1 403 Forbidden Content-Type: application/problem+json { "type": "about:blank", "title": "The supplied authentication is not authorized to access this resource" }
また私達のAPIはOpenAPI Specificationで書かれてswagger-uiからいつでも参照できるようになっています。 こちらには各APIごとのエラーレスポンスの仕様が細かく書かれていましたので、こちらも合わせて修正しました。
この仕様決定とドキュメントの作成・更新に比較的時間がかかり、だいたい合計5人日ぐらいかかったイメージです。
実装について
APIサーバはScala言語で書かれておりakka-httpフレームワークで作られています。 今までもRFC7807準拠ではなかったもののJSONフォーマットでエラーレスポンスを返していたので、だいたい実装期間は3人日程度でした。
リリースについて
修正内容に既存のAPI利用を阻害するような破壊的な内容がなかったため、通常通りのリリース手順でリリースしました。
API利用側の反応
2019/02/01現在アプリ側で増強されたエラーレスポンス情報を利用するコードが書かれておらず、まだフィードバックは特段ない状態です。
やってみた感想
エラーレスポンス仕様はまだ大手の公開APIでも完全にバラバラな状態で(参考: WebAPIでエラーをどう表現すべき?15のサービスを調査してみた - Qiita)各種WebフレームワークのRFC7807サポートもほとんどない状態ですが、個人の嗜好や趣味によって行き当たりばったりに決めるよりRFC準拠で実装することは様々なメリットがあります。 毎回APIの仕様を決めるときは数ある選択肢からどういったものにするか非常に悩むのですが、今回RFCという明確な指針に従ったことで非常に楽に仕様を決めることができました。今回決めた仕様は将来もっと良いものに拡張する可能性もありますが、今回はこちらでリリースしています。
各フレームワークも徐々にRFC7807をサポートしつつあるので導入はこれからもっと楽になると思います。
Add Media types for RFC 7807 by bigwheel · Pull Request #2323 · akka/akka-http*2
みなさんもっとRFC7807に従うことで、つまらない詳細の仕様に悩まずより重要なビジネスロジックに集中できるようにしましょう!