のべラボ.blog

Tech Blog | AWS や サーバーレスやコンテナ などなど

Amazon API Gateway のリクエスト本文検証時のエラーメッセージを変更してみる

Amazon API Gateway のリクエスト検証機能は広く知られているかもしれませんが、今回はリクエスト本文検証時のエラーメッセージを変更して詳細な情報を表示する方法を紹介します。

これは、数ヵ月前に私が登壇したトレーニングの受講者の質問から気づけた Tips です。(整理してブログで紹介しようと思っていながら遅れに遅れてしまいました 🙇‍♂️)

なお、この記事の内容は 2023 年 5 月に検証した内容に基づきます。


目次


Amazon API Gateway のリクエスト検証

Amazon API GatewayREST API では、API のリクエスト内容を検証できます。

docs.aws.amazon.com

例えば、特定のクエリ文字列パラメータや HTTP ヘッダ を必須とした場合、それがリクエストに含まれているかを検証したり、リクエスト本文が特定のフォーマットになっているかを検証できます。

今回は Amazon API GatewayAPI のサンプルとして使用できる PetStore API を使用して、リクエスト検証の機能についてみていきましょう。その後、リクエスト本文の検証時のエラーメッセージを変更していきます!


PetStore API の作成

AWS マネジメントコンソールから Amazon API Gateway のコンソールを表示し、API の作成を開始します。その際、API タイプとして [ REST API ] を選択して作成します。( [ REST API プライベート] ではないのでご注意ください。)

その後、下図のように [ API の例 ] を選択して ページ右下の[インポート] を選択します。

これで、サンプルである PetStore API が作成できました。


リクエストのクエリ文字列パラメータの検証

この PetStore API に必須のクエリ文字列を設定してみます。(もちろん、これはリクエストの検証機能を試すための設定で、PetStore API としては本来は必要ないものです。)

下図のように、[リソース] 、/pets の POST メソッド、[メソッドリクエス] の順で選択します。

そして、[リクエストの検証] で鉛筆アイコンをクリックして、 [本文、クエリ文字列パラメータ、およびヘッダーの検証] を選択し、右横のチェックマークをクリックします。これを選択したのは、あとで本文の検証も確認するためです。

[URL クエリ文字列パラメータ ] を展開表示して、[クエリ文字列の追加] を選択します。

鉛筆アイコンをクリックした後に表示される入力エリアに、クエリ文字列パラメータ名を入力します。今回はテスト用なのでどんな名前でもいいのですが、ここでは プレースホルダーに表示されている通り myQueryStringにしておきます。その後チェックマークをクリックして、[必須] にチェックをしておきましょう。

この設定により、PetStore API で /pets のパスで POST メソッドの API を発行する時は、クエリ文字列パラメータ名 として myQueryString が必須になりました。リクエストは検証され、もしこのパラメータが無い場合は、エラーとなるように設定できました。

この後、[アクション] から [API のデプロイ] を選択して、[デプロイされるステージ] として [新しいステージ] を選択します。[ステージ名] は任意ですがここでは [dev] と指定して [デプロイ] を選択します。

その後表示される [ URL の呼び出し:] の URL をメモしておきます。東京リージョンを使用している場合は、下記のような URL になっているはずです。

https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev

では curl コマンドを使用して API を実行してみます。

まず、myQueryString クエリ文字列パラメータを含めたリクエストを発行してみます。

curl -X POST  "<メモしておいたAmazon API Gateway のURL>/pets/?myQueryString=dummy" -H "Content-Type: application/json" -d '{ "type": "dog", "price": 50000  }' 

リクエストは正常に処理され、下記のようなレスポンスが表示されます。

  "pet": {
    "type": "dog",
    "price": 50000
  },
  "message": "success"
}

次にmyQueryString クエリ文字列パラメータなしでリクエストを発行してみます。

curl -X POST "<メモしておいたAmazon API Gateway のURL>/pets" -H "Content-Type: application/json" -d '{ "type": "dog", "price": 50000  }'  

下記のようなレスポンスが表示されます。メッセージをみると、必須パラメータが指定されていないということがわかります。

message": "Missing required request parameters: [myQueryString]"}

Amazon API Gateway のリクエスト検証が期待通りに動作していることが確認できました。


リクエストの本文の検証

次はリクエスト本文の検証を試しますが、PetStore API は、下図のようにすでに本文の検証が設定されています。

上図では [モデル名] として [NewPet] が指定されており、この NewPet モデルで定義されたスキーマに基づき本文の内容が検証されます。

このモデルの定義は、Amazon API Gateway のコンソールの左側のメニューから [モデル] を選択することで確認できます。

このモデルが参照している Type として PetType がありますが、これもコンソールから参照できます。

つまり、リクエスト本文のコンテンツタイプは application/json で、type キーと price キーが必要、また type の値は 文字列で "dog", "cat", "fish", "bird", "gecko" のいずれかでなくてはいけません。さらに price は数値でなくてはいけない、ということになります。

では、curl コマンドで確認します。正常処理はさきほどのクエリ文字列パラメータのテストで確認できているので、ここではスキーマに合致しない本文データを指定してみます。

curl -X POST "<メモしておいたAmazon API Gateway のURL>/pets/?myQueryString=dummy" -H "Content-Type: application/json" -d '{ "type": "tiger" ,"price": 50000  }' 

リクエストは検証され、スキーマに合致しないのでエラーになりました。

{"message": "Invalid request body"}

ただし、なぜエラーになったのか知りたい場合はどうすればいいでしょうか?この Invalid request body というエラーメッセージだけでは、本文のどこが正しくないのか判別できません。 もちろん、要件的にそれで問題ない場合もありますが、開発やテストフェーズでは検証エラーの理由を確認できた方が便利な場合もあります。

そこで、このデフォルトのエラーメッセージを変更してみます!


リクエストの本文の検証時のエラーメッセージの変更

下図のように、Amazon API Gateway のコンソールの左側のメニューで [ゲートウェイのレスポンス] 、[リクエスト本文が不正です] をクリックして、ページ右上の [編集] をクリックします。

[レスポンステンプレート] で [application/json] を選択して、[レスポンステンプレートの本文] を {"message":$context.error.validationErrorString} に変更して [保存] します。

$context.error.validationErrorString は、$context 変数とよばれるものの一種で、これを使用することで詳細な検証エラーメッセージを表示できます。

docs.aws.amazon.com

この変更後、Amazon API Gateway のコンソールの左側のメニューで [リソース] を選択して、もう一度 dev ステージを指定して API のデプロイを行ってください。

では、さきほどと同じスキーマに合致しないリクエストを発行してみます。

curl -X POST "<メモしておいたAmazon API Gateway のURL>/dev/pets/?myQueryString=dummy" -H "Content-Type: application/json" -d '{ "type": "tiger" ,"price": 50000  }' 

今回は下記のように、詳細なエラーメッセージを確認することができました。

message":[instance value (\"tiger\") not found in enum (possible values: [\"dog\",\"cat\",\"fish\",\"bird\",\"gecko\"])]}

その他、下記のようなパターンでリクエスト検証を試してみましたが、スキーマに合致しないリクエストはすべて詳細なエラーメッセージを表示することができました。

price に数値以外を指定した場合

curl -X POST "<メモしておいたAmazon API Gateway のURL>/pets/?myQueryString=dummy" -H "Content-Type: application/json" -d '{ "type": "dog", "price": "a"  }' 
message":[instance type (string) does not match any allowed primitive type (allowed: [\"integer\",\"number\"])]}

必要なキー( この例では price )がない場合

curl -X POST "<メモしておいたAmazon API Gateway のURL>/pets/?myQueryString=dummy" -H "Content-Type: application/json" -d '{ "type": "dog" }' 
  "errors": [
    {
      "key": "Pet2.price",
      "message": "Missing required field"
    }
  ]
}

今回の所感

これまで Amazon API Gateway のリクエスト検証の機能は触ったことがありましたが、ゲートウェイのレスポンス$ コンテキスト変数 についてはあまり触ったことがないため、よい気づきを得ることができました。 シンプルに Amazon API Gateway のリクエスト検証を使うだけでなく、さらに一歩進んだ Tips として活用していきたいと思います!


/* -----codeの行番号----- */