t0mmy

2020年12月30日に参加

学習履歴詳細

API デザインパターン 27章 リクエストの検証 読了

やったこと

  • API デザインパターン 27章 リクエストの検証 読了

学んだこと

ポイント

  • 検証リクエストとは何か
  • どうやって実装するか
  • 検証リクエストの振る舞いで気を付けるべきことは何か
  • 外部リソースへ依存する部分はどう検証するか

    学び

  • 検証リクエストは、取り返しのつかないような、危険なAPIリクエストの動作を検証するための機能

  • 検証用であることを示すプロパティ ( validateOnly など)を、リクエストボディに追加することで実装する

  • 検証リクエスト

    • 完全に安全かつ冪等性を持つメソッドになること
    • いかなるデータ変更も、副作用も引き起こしてはならなず、 同じ条件で実行した検証メソッドの結果は、常に同じであること
  • 検証リクエストは、外部依存も含め、可能な限り多くの面で検証し、通常(≒検証ではない)リクエストと同じ値を返す

    • 外部依存が検証機能を提供している場合、それを使用する
    • 提供していない場合、該当する外部依存の検証はスキップする ## 気づき
  • 検証リクエストは、validateOnlytrue を設定する必要がある点

    • 検証したいような慎重なエンジニアは、恐らくドキュメントを読み込み、検証手段がないか調べると思われる
    • そう考えると、明示的に true の場合のみ検証する ... という仕組みは納得できた

メモ

対象とする問題

安全なAPIリクエストは、実行することで試すことが出来る。
しかし、取り返しがつかないような、危険なAPIリクエストは、とりあえず実行...という手段はとれない。
そのため、APIリクエストが意図したものか検証できる機能が必要になる。

概要

API利用者が、APIリクエストのプレビューを取得できる機能を提供する。
この機能は、検証用リクエストと示すフラグを一つ設けることで十分達成できる。

validateOnly などの boolean型の変数を一つ設けるイメージ。

これにより、本番リクエストと同等の処理を検証(権限、一意性制約に反しないか、参照整合性に問題はないかなど)を実施できる。

実装

検証リクエストは、結果として、完全に安全かつ冪等性を持つメソッドになること。
いかなるデータ変更も、副作用も引き起こしてはならなず、 同じ条件で実行した検証メソッドの結果は、常に同じであること。

validateOnly のデフォルト値は false にする。
言い換えると、利用者が validateOnly を明示的に true と設定した場合のみ、検証処理を実施する。

  • デフォルトを true とすると、常にフラグを設定しないと、通常(≒検証ではない)のリクエストを実行できない
  • 明示的な指定を強制すると、大体間違いにつながる

検証リクエストでは、外部依存も含め、可能な限り多くの面で検証することが求められる。
レスポンスも、通常(≒検証ではない)リクエストと同じ値を返し、エラーコードも同じにすることが求められる。

外部依存関係

検証したい処理の中に、外部依存が存在する場合、どうやって安全性と冪等性を担保するか。

外部依存が検証機能を提供しているのであれば、これを利用する。
提供していないのであれば、その部分の検証はスキップする。

検証リクエストに求められる、以下の点は必ず守ること。

検証リクエストは、結果として、完全に安全かつ冪等性を持つメソッドになること。
いかなるデータ変更も、副作用も引き起こしてはならなず、 同じ条件で実行した検証メソッドの結果は、常に同じであること。


扱うこと

  • なぜいくつかのAPIメソッドは、リクエスト前に検証する必要があるのか
  • 検証リクエストにおける外部サービスとのやり取りをどのように管理するか
  • 検証リクエストにおけるメソッドの特殊な副作用に対処する

まとめ

  • APIリクエストの中には、非常な危険なものもある
    • そういったリクエストは、安全のため、事前に検証できる方法を提供するべきである
  • 検証機能は、 validateOnly のような、単純な boolean 型の値で提供する
    • システムには何の影響も与えない
  • 検証リクエストをサポートするAPIメソッドが外部サービスとやりとりすることは十分あり得る
    • 可能な限り外部依存を検証するべき
    • ただし、全外部依存の検証は不可能であることは明示する
WebAPI

2023年12月10日(日)

0.5時間