22 ポイント 投稿者 lemonmint 2025-06-02 | 5件のコメント | WhatsAppで共有

HTTP APIを開発する際、エラー処理はしばしば煩雑な部分になります。APIの数が増え、内部ロジックが複雑になるほど、3つの側面で難しさが生じます。

  • 適切なエラーコードの返却: 経験の浅い開発者の場合、複雑なロジックの中で一貫したHTTPステータスコードを使うのは簡単ではありません。
  • 大量の結果ログ作成: エラー発生時に想定されるすべての終了地点へログを記録することは、コード量を増やし、管理を複雑にします。
  • 明確なエラーメッセージの送信: クライアントへ単にエラーメッセージを渡すだけでは、エラーを明確に理解して処理するのが困難です。

適切なエラーコード返却の改善

エラーコード利用の一貫性の問題を解決するために、StatusCodeMessageを含むHttpErrorインターフェースまたは構造体を実装する方法を提案します。

  • 解決策:
    • HttpError型を定義: HTTPステータスコードとメッセージをカプセル化。
    • ヘルパー関数を提供: httperror.BadRequest("wrong format")のように、特定のエラーコードを返すヘルパー関数を使ってエラーオブジェクトを簡単に生成。
  • 利点:
    • IDEの自動補完機能を活用し、便利かつ安全にエラーコードとメッセージを入力可能。
    • 数値コードを手入力するよりも、ミスの発生可能性を低減。
    • あらかじめ用意された設計ドキュメントをいちいち確認する手間を削減。

ログ作成の集約

繰り返しのログ作成を減らし、エラー処理ロジックを1か所で管理するために、HTTPハンドラーをラップする方法を示します。

  • 解決策:
    • カスタムルーター(chiwrap.Router)の実装: chi.Routerのような既存ルーターを内部に含み、エラー処理ロジックを追加します。
    • ハンドラーのラップ: カスタムルーターのGetなどのメソッドはHandlerFuncを受け取り、内部で実行し、エラーが発生した場合は集約処理ロジックへ渡します。
    • エラーコールバック関数: NewRouter作成時にerrCallback関数を受け取り、エラー発生時にそのコールバックを呼び出して、中央でログを記録したり追加処理を行ったりします。
  • 利点:
    • APIロジックでエラーが発生すると、自動的に適切なエラーコードとメッセージがレスポンスとして返される。
    • サービスごとに適切なログを記録するようコールバック関数を登録でき、ログ管理が容易。
    • コードの重複を減らし、保守性を向上。

明確なエラーメッセージの送信(RFC7807の活用)

クライアントがエラーをより明確に理解して処理できるよう、RFC7807標準を活用した構造化エラーメッセージの送信方法を提案します。

  • RFC7807の主要要素:
    • type: エラー種別を識別するURI(例: https://example.com/errors/validation)。
    • title: エラーに関する短い1行説明。
    • status: HTTPステータスコードと同じ。
    • detail: 人が読める詳細なエラー説明。
    • instance: エラーが発生した特定のURI(例: /api/users/abc)。
    • extensions: 追加情報を含むJSONオブジェクト(例: invalid_field, expected_format)。
  • 実装:
    • RFC7807Error構造体を作成し、主要要素を含める。

    • メソッドチェーンパターン(WithType(), WithInstance(), WithExtension())によって、構造化されたエラーオブジェクトを簡単に生成。

    • ToHttpError()メソッドを通じてRFC7807ErrorHttpErrorに変換し、集約ルーターと連携可能。

    • クライアントがエラーの種類、原因、発生位置などを明確に把握可能。

    • APIレスポンスの一貫性と有用性を高め、クライアント開発の効率を向上。

5件のコメント

 
aer0700 2025-06-02

良い記事をありがとうございます

 
beoks 2025-06-02

良い記事をありがとうございます!
参考までに、Spring では spring-web ライブラリの org.springframework.http.ProblemDetail に実装が存在します!

 
honglu 2025-06-02

良い紹介をありがとうございます!
調べてみたところ、RFC 9457 に置き換えられていましたね。

https://datatracker.ietf.org/doc/html/rfc9457
(従来の 7807 文書: https://datatracker.ietf.org/doc/html/rfc7807)

 
findnamo 2025-06-02

RFC 7807 と RFC 9457 の主な違い

  • 問題タイプ管理: 7807 はカスタム URI のみ使用可能、9457 は IANA 共有レジストリを導入
  • 複数エラー処理: 7807 は HTTP 207 ステータスコードの使用を推奨、9457 は単一の問題タイプ内で errors 配列を使って関連エラーをグループ化
  • 拡張フィールド: 7807 は任意フィールドを追加可能、9457 は問題タイプごとの想定フィールドを明示的に関連付け
  • セキュリティ勧告: 7807 には含まれないが、9457 ではセキュリティ脆弱性を防ぐための明示的な指針を追加
  • JSON Pointer: 7807 は未対応、9457 は pointer フィールドを正式サポート

2023年7月以降の新規プロジェクトでは RFC 9457 の適用を推奨

 
honglu 2025-06-02

type フィールドは、参照解決可能な URI に設定することが推奨されているようです。

内部サービスでは、Swagger-ui のドキュメントリンクで代用しても問題ないと思います。