web-dev-qa-db-ja.com

サードパーティのAPIからの応答を検証することは一般的な方法ですか?

私はいくつかのサードパーティサービスに依存するPHP Webアプリケーションに取り組んでいます。これらのサービスは十分に文書化され、かなり大きな組織によって提供されています。

これらのAPIからの応答を操作するとき、私は偏執的だと感じます。これにより、応答がドキュメントで指定された構造とデータ型に一致することを検証する検証コードを書くようになります。これは主に、それが私の制御不能であり、データが正しいことを盲目的に信頼し、そうでない場合(誰かが誤ってjson構造を変更した場合)である場合、アプリケーションで予期しない動作が発生する可能性があるという事実に起因します。

私の質問は、これはやり過ぎだと思いますか?他の誰もがこの状況をどのように処理しますか?

42
Darren Findlay

もちろんです。手始めに、誰かがあなたの接続にハッキングしていないこと、そしてあなたが受け取った応答がAPIからまったく来ていないことを決してあなたは知らない。

また、過去2週間のうちに、Facebookが予告なしにAPIを変更したため、多くのiOSアプリがクラッシュしたと思うことがあります。誰かが返信を確認した場合、APIは失敗しましたが、アプリはクラッシュしませんでした。

(検証が必要な理由を聞いた非常に良いケース:サーバーは顧客が購入できる商品に関する情報を提供しました。ドレスの場合、英国のドレスサイズを36から52の整数として含めました。1つのドレスを除いて、サイズは文字列「40-42」。検証しないと簡単にクラッシュする可能性があります。

64
gnasher729

他の誰かのAPIがあなたの外部インターフェースです。その境界を越えるものを盲目的に信頼すべきではありません。将来のデバッガは、他のシステムのエラーを自分のシステムに伝播しないことを感謝します。

40
Ross Patterson

あなたのAPI境界は信頼境界でもありますか?

リモートシステムと通信しているので、それはほぼ確実です。リモートシステム自体が信頼されている可能性があっても、メディアは信頼されていない可能性があります。

すべての信頼できないデータを首尾よく一貫して検証できないと、最悪の場合、最悪の場合、サイレント敵対的乗っ取りがクラッシュする可能性があります。

APIは安定していますか?

信頼できるAPIでも安定しない可能性があります。その場合、追加の検証が必要であり、修正されるまでサービスを拒否するまでのバックアウトの計画が必要です。

APIの背後にある実装は十分にテストされ、成熟していて信頼性がありますか?

実装が適切に機能しない場合、APIが安定しているかどうかは関係ありません。

常にトレードオフがあることを忘れないでください

テストが増えると、バグが含まれる可能性があるコードが増えることを意味します。

このコードは、作成、保守、およびデバッグする必要があります。これらはすべて、他の場所でも必要な労力を浪費します。

また、完全なAPIをモックしない限り、障害ケースを包括的にテストすることは困難と不可能の中間であり、コメントよりも遅くても、バグが発見されずに蓄積され続ける可能性があります。

したがって、some APIは機能するために単に依存していますが、他のAPIは各呼び出しで少なくともある程度は検証されます(または少なくとも検証されるべきです)。

17
Deduplicator

妄想かどうかは、ソフトウェアの堅牢性に依存します。

私は、あなたの小切手が最小限の追加の実装コストを持っているなら、それらは大丈夫だと思います。

例:

  • xMLを介してサービスと通信する場合、構造検証はXSDスキーマを介して実行できます。
  • java/C#では、 APIコントラクトが壊れている の場合、例外をスローするガードステートメントを使用できます。
    • 例:外部サービスから誕生日を取得した場合、誕生日にもっともらしい値が含まれている場合、guard-statement assert(birthday > '1900-01-01' and birthday < '2050-01-01')は例外をスローします
3
k3b

もちろんです。たとえば、Microsoft APIでこれに悩まされており、 Azure 関数アプリケーションにそれを記録するように設定されていませんでした。つまり、エンドポイントへのリクエストが失敗したことだけがわかりました。これは、手のテスト/ [〜#〜] uat [〜#〜] とアプリケーションの実際のライブ使用の間で警告なしに変更されました。

私たちの単体テストは、Microsoftドキュメント(notが更新されていた)のスキーマを使用していたため、もちろん機能しました。他の親切な開発者がマイクロソフトのドキュメントにコメントしたので私は知っていました!

外部APIからエンドポイントへの要求として実際に取得したものをログに記録し、呼び出しへの応答として記録し、アプリケーションに意味のあるエラー(適切な場合)をスローしてください。

これは実際に、多くの外部APIに依存している現在のプロジェクトの意欲を与えます-監視機能と E2E テスト Cypress を使用して、頻繁に実行される重要な機能があるため、少なくともいつ発生するかはわかっています。私たちはまだ事前に確実に知る方法に取り組んでいます...

3
kpollock

はい、しかしほとんどの場合それはあなたの個人的な心配ではありません。

ほとんどの言語には、ネイティブJSON(または転送言語が何であれ)の応答を内部オブジェクトに解析するパーサーがあります。さまざまな書き込みスタイルを考慮したり、コーナーケース、エスケープ文字、特殊文字エンコーディングなどを理解するためのすべてのオプションが用意されています。検証コードは、他の何千ものアプリケーションで使用されています。可能であれば、これらのパーサーのいずれかを使用して、構文を自分で検証するのではなく、それらの検証メソッドに依存する必要があります。つまり例外をスローするか、エラーコードを返すか、入力が指定したものと一致しない場合(フィールドが欠落している場合、文字列が定義済みのパターンと一致しない場合など)に文句を言う必要があります。

独自のコードで自分で実行する可能性がある唯一の検証は、応答がビジネスロジックにとって意味があることです。ただし、他のサービスを再実装しようとしないでください。応答が正しいことを完全に検証しても意味がありません。ローカルで実行できる場合は、呼び出す必要はありません。 (完全にデリケートな問題や難しい問題に対処しない限り、複数のサービスを呼び出してその結果を組み合わせることができます)。悪意のある応答から極端なレベルの災害から保護したい場合にできることは、範囲外の答えを検出することです。つまり1人の顧客に対して外部で計算された請求額が1000ドルを超える場合は、自転車レンタルサービスでトランザクションをブロックします。しかし、注意してください。有効なコーナーケースを見落としがちです(たとえば、会社全体のレンタル料を1年間支払う「仮想」顧客)。

3
Frank Hopkins

検証は制限的であってはなりません。 「寛容な読者」パターンがあります。つまり、他のサービスからデータを消費するときは、できるだけ寛容であるべきです。反対側には、「大作家」のパターンがあります。一緒に、彼らはより堅牢な通信システムを生成するのに役立ちます。

たとえば、JSONベースのインターフェースでは、おそらく不明なプロパティを許可する必要があります。これにより、相手側を壊すことなく新しいプロパティを追加できます。

3
user355880