今から始めるLambda④「API Gatewayと組み合わせる」
はじめに
前回の記事ではLayersの仕様・作成方法、Lambdaの関数と連携する方法などを紹介しました。
今回はLambdaとAPI Gatewayを連携させてREST APIを作成する方法を紹介します。
参考
以下の記事を参考に進めています。
※一部変更している箇所があります。
Lambda
以下のようなLambdaは作成されているものとします。
ランタイムはNode.jsで、名称はapiFunctionとします。
exports.handler = async (event, context) => {
    const response = {
        statusCode: 200,
        body: JSON.stringify('This fuction is apiFunction2'),
    };
    context.done(null, response)
};
後々使用するため、下記コマンドでARNを取得しておくとよいです。
aws lambda list-functions
REST APIの作成
早速REST APIを作成していきます。
名前はTestAPIとします。
aws apigateway create-rest-api --name TestAPI --description "This is test API"
このコマンドのレスポンスは以下のようになります。
{
    "id": "【REST_API_ID】",
    "name": "TestAPI",
    "description": "This is test API",
    "createdDate": "2021-10-21T13:56:55+09:00",
    "apiKeySource": "HEADER",
    "endpointConfiguration": {
        "types": [
            "EDGE"
        ]
    },
    "disableExecuteApiEndpoint": false
}
この中のREST_API_IDはこの後も使うので控えておくとよいです。
リソースの確認
作成したREST API中のリソースを確認します。
aws apigateway get-resources --rest-api-id 【REST_API_ID】
この時点(デフォルト)では/のみとなっていることが分かります。
{
    "items": [
        {
            "id": "【ROOT_RESOURCE_ID】",
            "path": "/"
        }
    ]
}
リソースの追加
ここに/hogeというリソース(パス)を追加します。
REST_API_IDと親にしたいリソースのID(ROOT_RESOUCE_ID)を指定します。
ここに先ほどの/のリソースIDを指定します。
aws apigateway create-resource --rest-api-id 【REST_API_ID】 --parent-id 【ROOT_RESOUCE_ID】 --path-part "hoge"
再度確認コマンドを打つと、/hogeが増えていることが分かります。
※以降/hogeリソースのIDをHOGE_RESOURCE_IDとします。
Lambdaとの紐付け
冒頭で紹介したLambdaとREST APIの接続を行います。
クライアントからリクエストが届き、レスポンスが返るまでには以下の4フローがあります。
- クライアントから
API Gatewayへリクエストが届く- ここで認証チェックもするらしい
 
 - 
API GatewayがリソースやHTTP Methodに対応したLambdaを呼び出す - 
LambdaからAPI Gatewayへレスポンスを返す - 
API Gatewayからクライアントにレスポンスを返す 
API Gatewayでは、上記の4ステップそれぞれを設定する必要があります。
①Method Request(クライアントから API Gateway へのリクエスト)
今回は認証を通さず、APIKEYも必要とせず、特にリクエストパラメータもないものとするので
--authorization-type NONE --no-api-key-required --request-parameters {}というオプションを付けます。
aws apigateway put-method --rest-api-id 【REST_API_ID】 --resource-id 【HOGE_RESOURCE_ID】 --http-method GET --authorization-type NONE --no-api-key-required --request-parameters {}
これがうまくいくと以下のようなレスポンスが返ります。
{
    "httpMethod": "GET",
    "authorizationType": "NONE",
    "apiKeyRequired": false,
    "requestParameters": {}
}
②put-integration(API Gateway から Lambda へのリクエスト)
API GatewayからLambdaを叩きます。
uriは"arn:aws:apigateway:【REGION】:lambda:path/2015-03-31/functions/【Lambdaの関数のARN】/invocations"の形式となっているので、以下のようにオプションを指定します。
aws apigateway put-integration --rest-api-id 【REST_API_ID】 --resource-id 【HOGE_RESOURCE_ID】 --http-method GET --integration-http-method POST --type AWS --uri "arn:aws:apigateway:【REGION】:lambda:path/2015-03-31/functions/【Lambdaの関数のARN】/invocations"
うまくいくと以下のレスポンスが返ります。
{
    "type": "AWS",
    "httpMethod": "POST",
    "uri": "arn:aws:apigateway:【REGION】:lambda:path/2015-03-31/functions/【Lambdaの関数のARN】/invocations",
    "passthroughBehavior": "WHEN_NO_MATCH",
    "timeoutInMillis": 29000,
    "cacheNamespace": "kp0l6p",
    "cacheKeyParameters": []
}
③put-integration-response(Lambda から API Gateway へのレスポンス)
返却するレスポンスのフォーマットを指定します。
ここでいうところの{"application/json": ""}です。
aws apigateway put-integration-response --rest-api-id 【REST_API_ID】 --resource-id 【HOGE_RESOURCE_ID】 --http-method GET --status-code 200 --response-templates '{"application/json": ""}'
うまくいくと以下のレスポンスが返ります。
{
    "statusCode": "200",
    "responseTemplates": {
        "application/json": null
    }
}
④put-method-response(API Gateway からクライアントへのレスポンス)
今回はLambdaからのレスポンスをAPI Gatewayはそのまま返すイメージなので、③とほぼ似たようなコマンドになります。
aws apigateway put-method-response --rest-api-id 【REST_API_ID】 --resource-id 【HOGE_RESOURCE_ID】 --http-method GET --status-code 200 --response-models '{"application/json": "Empty"}'
パーミッション設定
API GatewayがLambdaを実行できるように権限を設定します。
--statement-idは任意の値、--source-arnは "arn:aws:execute-api:【REGION】:【ACCOUNT_ID】:【REST_API_ID】/*/【HTTPメソッド】/【リソース名】"の形式になります。
aws lambda add-permission --function-name apiFunction --statement-id api_lamda_test --action "lambda:InvokeFunction" --principal  apigateway.amazonaws.com --source-arn "arn:aws:execute-api:【REGION】:【ACCOUNT_ID】:【REST_API_ID】/*/GET/hoge"
これで一通りの設定は完了です。
続いてテストをしてみましょう。
テスト実行
test-invoke-methodで検証ができます。
aws apigateway test-invoke-method --rest-api-id 【REST_API_ID】 --resource-id 【HOGE_RESOURCE_ID】 --http-method GET --path-with-query-string ''
statusCode=200で返ってくればOKです。
デプロイ
実際に作成したREST APIを適用(デプロイ)します。
この時、ステージ名を指定してデプロイを行う必要があります。
※このステージ名もREST APIのパスに含まれる。
aws apigateway create-deployment --rest-api-id 【REST_API_ID】 --stage-name test --stage-description "This is a test api" --description "API Gateway to Lambda Test"
デプロイ情報、ステージ情報の取得
以下のコマンドを叩いて、先ほど入力した情報が出力されていれば成功です。
aws apigateway get-deployments --rest-api-id 【REST_API_ID】
aws apigateway get-stages --rest-api-id 【REST_API_ID】
ブラウザから検証
REST APIのリンクは"https://【REST_API_ID】.execute-api.【REGION】.amazonaws.com/【ステージ名】/【リソース名】"となります。
以下のリンクをブラウザから叩いてみて、テスト時と同じレスポンスが返って来れば成功です。
https://【REST_API_ID】.execute-api.【REGION】.amazonaws.com/test/hoge
後片付け
最後に今回作成したREST APIの後片付けを行います。
API GatewayやLambdaには無料枠がありますが、攻撃を受けたりしてリクエスト回数が嵩むと料金が発生する可能性があるので、必ず行っておきましょう。
REST_API_IDを指定して削除を行います。
aws apigateway delete-rest-api --rest-api-id 【REST_API_ID】
先ほどのリンクを叩いて、表示されなくなればOKです。
まとめ
今回はAPI GatewayとLambdaとの接続方法について紹介しました。
今回はGETリクエストでしたが、POSTリクエストを作成したい場合も手順はほとんど同じで、put-methodの時のオプション--http-methodがPOSTになったり、パーミッションの--source-arn中のGETがPOSTになっていたりと、一部オプションが変わるだけです。
ここにさらにCognitoを加えての認証や、AuroraやDynamoDBを絡めたデータのやりとりを加えることで、一般的なREST APIを作成することができます。
その内容については別記事としたいと思います。
今回の内容が役立ちましたら幸いです。
Discussion