- Amazon API Gatewayの使い方とクエリ文字列パラメータの渡し方
- リソースの作成
- メソッドの作成
- テストを実行する
- URLクエリ文字列パラメータをLambda関数に渡す
- パスパラメータを設定してマッピングテンプレートで渡す
- リクエストボディ部をマッピングテンプレートで渡す
- マッピングテンプレートで使用するVelocity Template Language(VTL)
- Lambdaプロキシの統合の使用
- curlでリクエストボディのバリデーションチェックを行う
- Lambdaプロキシの統合の使用にチェックを入れてPOSTでデータ送信する
- リクエストのモデルを作成する
- リクエストの検証
- モデルでnullを許容する
- メソッドレスポンスのレスポンス本文(メソッドレスポンスモデル)
- Cognitoで保護したAPI GatewayをPOSTMANでテストする
- 関連
Amazon API Gatewayの使い方とクエリ文字列パラメータの渡し方
Amazon API Gatewayの使い方についてです。 「新しいAPIの作成」画面でAPI名を入力し、「APIの作成」をクリックします。
リソースの作成
次にリソースの作成を行います。
リソース名を適当に入力します。これがURLの一部になります。
「リソースの作成」をクリックすると、リソースが作成されます。
メソッドの作成
次にそのリソースに対してメソッドを作成します。
「メソッドの作成」を押下すると、コンボボックスがでてきますので、ここでは「GET」を指定します。
「GET」の右側にあるチェックを押すと確定されます。 AWS GatewayからLambda関数を呼び出してみます。
Lambdaリージョンを指定し、Lambda関数は適当に作ったgetgetgetという関数を指定し、「保存」を押します。以下のように権限を与える旨のメッセージがでますので「OK」を押します。
ちなみにgetgetgetは以下になります。
テストを実行する
これでAPI GatewayからLambdaを呼び出すことができるようになりました。 実際にテストをしてみます。
「テスト」をクリックします。
この画面で「テスト」をクリックすると、右側に結果が表示されます。
URLクエリ文字列パラメータをLambda関数に渡す
API Gatewayでクエリ文字列パラメータを定義します。「メソッドリクエスト」をクリックします。
「クエリ文字列の追加」をクリックします。
以下のように入力できるようになるので、ここでは「ID」と入力します。
右側のチェックをクリックすれば確定です。 つぎに「統合リクエスト」をクリックします。
「本文マッピングテンプレート」を開き、「マッピングテンプレートの追加」をクリックします。
Content-Typeは、「application/json」にします。すると、以下の画面が表示されます。
入力欄に、以下のように記述します。
{ "ID": "$input.params("userid")", "LANG": "$input.params("lang")" }
IDがAPI Gatewayから渡される値で、IDはevent.IDというようにLambda関数でアクセスすることができます。 実際にテストしてみます。IDにはオブジェクトを渡します。
Lambda関数では、event.XXを返しているだけです。結果は以下のようになります。
パスパラメータを設定してマッピングテンプレートで渡す
パスパラメータはリソース部分で設定してあげる必要があります。 「リソースの作成」で以下のように指定します。
リソース名は{}で囲まないですが、リソースパスは、{}で囲ってあげます。 useridというパスパラメータが作成されているのが確認できます。
パスパラメータはクエリ文字列パラメータ同様、$input.params(“~~~”)と指定してあげたらOKです。
リクエストボディ部をマッピングテンプレートで渡す
リクエストボディ部は$input.bodyで取得し、Lambdaなどに渡してあげます。
マッピングテンプレートで使用するVelocity Template Language(VTL)
「本文マッピングテンプレート」を開いたら、VTLという言語を用いてクエリパラメータを予期に計らってくれる機能があります。
例えば、?lang=jaまたは?lang=enというクエリ文字列パラメータを付加されるURIがあるとします。
langが未指定の場合はデフォルトjaとしたいといった場合、VTLを用いてapi gatewayで設定してしまいます。
#if($input.params('lang') == "ja") #set($value = "ja") #elseif($input.params('lang') == "en") #set($value = "en") #else #set($value = "ja") #end { "lang":"$value" }
こうすることによってLambda側で余計なチェックロジックなどのコーディングが不要になります。 The Apache Velocity Project
Lambdaプロキシの統合の使用
「統合リクエスト」をクリックすると、「Lambdaプロキシの統合の使用」があるので、チェックをします。
これにチェックを入れると、「統合レスポンス」の設定ができなくなります。
また、Lambda関数の戻り値は以下の形式で返す必要があります。
var responseBody = { message: "クエリ: ," + event.queryStringParameters.XX + "!", input: event }; var response = { statusCode: responseCode, headers: { "x-custom-header" : "my custom header value" }, body: JSON.stringify(responseBody) };
body部は、オブジェクトではなく文字列でないといけないので注意です。JSON.stringify()せずにそのままJSONオブジェクトを返すと502エラーとなります。
・statusCode,headers,bodyは必須になる(bodyは文字列)
また、event.XXでアクセス出来ていたクエリ文字列が、以下のように「event.queryStringParameters.XX」を追加する必要があります。
パスパラメータは、event.pathParameters.YYというようにすればLambda側で取得することが可能になります。
リクエストボディは、event.bodyで取得することが可能になります。
event.queryStringParameters.XX
curlでリクエストボディのバリデーションチェックを行う
curlでリクエストボディのバリデーションチェックを行うには、ヘッダ情報にContent-Type:application/json
を指定する必要があります。
指定しない場合、リクエストボディのバリデーションチェックはcurlコマンドでは行われないので注意が必要です。
一時的にリクエストボディのチェックをしたくない場合はContent-Typeを指定しなければapplication/x-www-form-urlencoded
になるようなのでリクエストボディのバリデーションチェックを無効にすることが出来ます。
Lambdaプロキシの統合の使用にチェックを入れてPOSTでデータ送信する
今度はLambdaプロキシの統合の使用にチェックを入れてPOSTしてみます。POSTにするには、「メソッドの作成」でPOSTを選択するとPOSTになります。
「テスト」をクリックします。
クエリ文字列、ヘッダーは空のまま、リクエスト本文に以下を設定します。
{ "ID":"test", "DATA":[ { "category":"1", "type":"2" } ] }
以下のような感じです。
Lambda関数はシンプルにDATAの値を返しています。
exports.handler = (event, context, callback) => { let obj = JSON.parse(event.body); let responseBody = { message: obj.DATA }; let response = { statusCode: 200, headers: {}, body: JSON.stringify(responseBody) }; callback(null, response); };
POSTの際に注意しないといけないのは、オブジェクトで渡してもLambda側では文字列で渡ってくるという点です。
なので、event.bodyはJSON.parseしてあげないといけません。
API Gatewayのテストをすると結果は以下のようになります。
リクエストのモデルを作成する
モデルを作成することによってクエリの必須チェックなどが簡単にできるようです。
POSTのデータに対して必須チェックするのには役に立つのかもしれませんが、JSON Schemaで記述する必要があるので非常に書きづらいです。
上記の「モデル」をクリックします。「作成」ボタンがありますので押すと以下の入力画面が表示されます。
「モデルのスキーマ」欄に記述していきます。以下、IDを必須とした例です。
{ "title": "タイトル", "type": "object", "properties": { "ID": { "type": "string" } }, "required":["ID"] }
「モデルの作成」をクリックすると、モデルが作成されます。 このモデルを、メソッドリクエストと紐づけます。API Gatewayのメソッドを指定します。
リクエスト本文をクリックすると、以下のように「モデルなし」となっています。
「モデルの追加」をクリックします。
コンテンツタイプは「application/json」、モデル名は先ほど作成したモデルがプルダウンで表示されますので、それを選択して、右側のチェックを押して設定完了です。
必須項目がnullだったりすると、以下のようにエラーで怒られます。
{ "message": "Invalid request body" }
※2020/01/25追記
OpenAPI3.0をAPI Gatewayにインポートすると、自動でメソッドリクエストのリクエスト本文(モデル)を生成してくれます。
ただ、Open API3.0.1で有効なキーワードが、JSON Schemaのドラフト4ではまだ無効のケースがあるので、注意が必要です。
とりあえず、以下はドラフト7から追加されているため、API Gatewayでは無効です。
キーワード | draft-04 |
---|---|
default | × |
date | × |
time | × |
リクエストの検証
リクエストの検証を「なし」にすると、クエリ文字列パラメータやHTTPリクエストヘッダー、リクエスト本文(JSONスキーマモデル)のチェックはすべて無視されます。
モデルでnullを許容する
“ID”: { “type”: “string” } 上記のように記述すると、nullを指定するとInvalid request bodyエラーとなります。
stringもしくはnullを許容したい場合は以下のように配列で[“string”, “null”]というように記述する必要があります。
{ "title": "タイトル", "type": "object", "properties": { "ID": ["string", "null"] } }
メソッドレスポンスのレスポンス本文(メソッドレスポンスモデル)
ここでもレスポンスのモデルを指定することができますが、メソッドリクエストのリクエスト本文とは違い、バリデーションは行ってくれません。
Cognitoで保護したAPI GatewayをPOSTMANでテストする
POSTMANのAuthorization Typeを「No Auth」にします。
ヘッダに「Authorization」があるので、このValueに認証トークンを貼り付けます。※console.logなどから取得してください。
これでCognitoで保護されたAPI GatewayもPOSTMANからテストすることができます。
KHI入社して退社。今はCONFRAGEで正社員です。関西で140-170/80~120万から受け付けております^^
得意技はJS(ES6),Java,AWSの大体のリソースです
コメントはやさしくお願いいたします^^
座右の銘は、「狭き門より入れ」「願わくは、我に七難八苦を与えたまえ」です^^
コメント