チュートリアル: Amazon API Gateway で AWS Lambda を使用する
この例では、Amazon API Gateway を使用してシンプルな API を作成します。Amazon API Gateway はリソースとメソッドの集合体です。このチュートリアルでは、1
つのリソース (DynamoDBManager
) を作成し、それに対する 1 つのメソッド (POST
) を定義します。このメソッドでは-Lambda 関数 (LambdaFunctionOverHttps
) が使用されます。つまり、HTTPS エンドポイントで API を呼び出すと、Amazon API Gateway が Lambda 関数を呼び出します。
DynamoDBManager
リソースの POST
メソッドでは、以下の DynamoDB オペレーションがサポートされます。
-
項目を作成、更新、削除する。
-
項目を読み取る。
-
項目をスキャンする。
-
テストに使用できる、DynamoDB に関連しないその他のオペレーション (echo、ping)。
POST
リクエストで送信するリクエストペイロードによって、DynamoDB オペレーションが識別され、必要なデータが提供されます。例:
-
DynamoDB の項目の作成オペレーションのリクエストペイロードの例を以下に示します。
{ "operation": "create", "tableName": "lambda-apigateway", "payload": { "Item": { "id": "1", "name": "Bob" } } }
-
DynamoDB の Read Item オペレーションのリクエストペイロードの例を以下に示します。
{ "operation": "read", "tableName": "lambda-apigateway", "payload": { "Key": { "id": "1" } } }
-
echo
オペレーションのリクエストペイロードの例を以下に示します。リクエストボディに以下のデータを使用して、HTTP POST リクエストをエンドポイントに送信します。{ "operation": "echo", "payload": { "somekey1": "somevalue1", "somekey2": "somevalue2" } }
API Gateway には、次のような高度な機能があります。
-
リクエスト全体のパススルー –
AWS_PROXY
統合タイプを使用して、Lambda 関数で HTTP リクエスト全体 (リクエストボディだけでなく) を受信し、HTTP レスポンス (レスポンス本文だけでなく) を設定できます。 -
キャッチオールメソッド –
ANY
キャッチオールメソッドを使用して、API リソースのすべてのメソッドを単一のマッピングを使用する単一の Lambda 関数にマッピングできます。 -
キャッチオールリソース – 新しいパスパラメータ (
{proxy+})
) を使用して、リソースのすべてのサブパスを、追加構成を必要とせずに Lambda 関数にマッピングできます。
これらの API ゲートウェイ機能の詳細については、「プロキシリソースのプロキシ統合を設定する」を参照してください。
前提条件
このチュートリアルでは、基本的な Lambda オペレーションと Lambda コンソールについてある程度の知識があることを前提としています。まだ作成していない場合は、「AWS Lambda の開始方法」の指示に従って、最初の Lambda 関数を作成します。
次のステップを完了するには、コマンドを実行するコマンドラインターミナルまたはシェルが必要です。コマンドは、該当する場合、プロンプト記号 ($) と現在のディレクトリの名前が前に付けられて、リストに示されます。
~/lambda-project$ this is a command
this is output
コマンドが長い場合は、エスケープ文字 (\
) を使用して、コマンドを複数の行に分割します。
Linux および macOS では、任意のシェルとパッケージマネージャーを使用します。Windows 10 では、Linux 用の Windows サブシステムをインストール
実行ロールを作成する
AWS リソースにアクセスするためのアクセス権限を関数に付与する実行ロールを作成します。
実行ロールを作成するには
-
IAM コンソールの [Roles] ページ
を開きます。 -
[ロールの作成] を選択します。
-
次のプロパティでロールを作成します。
-
信頼されたエンティティ – Lambda
-
ロール名 –
lambda-apigateway-role
。 -
[アクセス許可] – DynamoDB および CloudWatch Logs のアクセス許可を含むカスタムポリシー。
{ "Version": "2012-10-17", "Statement": [ { "Sid": "Stmt1428341300017", "Action": [ "dynamodb:DeleteItem", "dynamodb:GetItem", "dynamodb:PutItem", "dynamodb:Query", "dynamodb:Scan", "dynamodb:UpdateItem" ], "Effect": "Allow", "Resource": "*" }, { "Sid": "", "Resource": "*", "Action": [ "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents" ], "Effect": "Allow" } ] }
-
カスタムポリシーには、関数がデータを DynamoDB に書き込んでログをアップロードするために必要なアクセス許可が含まれています。後で使用できるようにロールの Amazon リソースネーム (ARN) をメモします。
関数を作成する
以下のコード例では、API Gateway イベント入力を受け取り、含まれるメッセージを処理します。このコードでは説明のために、受信イベントデータの一部が CloudWatch Logs に書き込まれます。
他の言語によるサンプルコードについては、「サンプル関数コード」を参照してください。
例 index.js
console.log('Loading function'); var AWS = require('aws-sdk'); var dynamo = new AWS.DynamoDB.DocumentClient(); /** * Provide an event that contains the following keys: * * - operation: one of the operations in the switch statement below * - tableName: required for operations that interact with DynamoDB * - payload: a parameter to pass to the operation being performed */ exports.handler = function(event, context, callback) { //console.log('Received event:', JSON.stringify(event, null, 2)); var operation = event.operation; if (event.tableName) { event.payload.TableName = event.tableName; } switch (operation) { case 'create': dynamo.put(event.payload, callback); break; case 'read': dynamo.get(event.payload, callback); break; case 'update': dynamo.update(event.payload, callback); break; case 'delete': dynamo.delete(event.payload, callback); break; case 'list': dynamo.scan(event.payload, callback); break; case 'echo': callback(null, "Success"); break; case 'ping': callback(null, "pong"); break; default: callback('Unknown operation: ${operation}'); } };
関数を作成するには
-
サンプルコードを
index.js
という名前のファイルにコピーします。 -
デプロイパッケージを作成します。
$
zip function.zip index.js
-
create-function
コマンドを使用して Lambda 関数を作成します。$
aws lambda create-function --function-name LambdaFunctionOverHttps \ --zip-file fileb://function.zip --handler index.handler --runtime nodejs12.x \ --role
arn:aws:iam::123456789012:role/service-role/lambda-apigateway-role
Lambda 関数をテストする
サンプルイベントデータを使用して手動で関数を呼び出します。コンソール UI では、実行の要約、ユーザーのコードによって書き込まれたログ、関数が返した結果 (コンソールでは常に同期実行される
— RequestResponse
呼び出しタイプを使用して Lambda 関数を呼び出す) などの実行結果の確認用にユーザーに分かりやすいインターフェイスが提供されているため、コンソールを使用して関数を呼び出すことをお勧めします。
Lambda 関数をテストするには
-
以下の JSON をファイルにコピーし、
input.txt
という名前で保存します。{ "operation": "echo", "payload": { "somekey1": "somevalue1", "somekey2": "somevalue2" } }
-
以下の
invoke
コマンドを実行します。$
aws lambda invoke --function-name LambdaFunctionOverHttps \ --payload fileb://input.txt outputfile.txt
Amazon API Gateway を使用して API を作成する
このステップでは、Amazon API Gateway を使用して作成した API 内のメソッドに Lambda 関数を関連付け、エンドツーエンドエクスペリエンスをテストします。つまり、HTTP リクエストが API メソッドに送信されると、Amazon API Gateway は Lambda 関数を呼び出します。
最初に、Amazon API Gateway を使用して、1 つのリソース (DynamoDBManager
) と 1 つのメソッド (POST
) を持つ API (DynamoDBOperations
) を作成します。POST
メソッドを Lambda 関数に関連付けます。次に、エンドツーエンドエクスペリエンスをテストします。
API の作成
次の create-rest-api
コマンドを実行して、このチュートリアル用の DynamoDBOperations
API を作成します。
$
aws apigateway create-rest-api --name DynamoDBOperations
{ "id": "bs8fqo6bp0", "name": "DynamoDBOperations", "createdDate": 1539803980, "apiKeySource": "HEADER", "endpointConfiguration": { "types": [ "EDGE" ] } }
別のコマンドで使用できるように API ID を保存します。API のルートリソースの ID も必要です。この ID を取得するには、get-resources
コマンドを実行します。
$
API=
$bs8fqo6bp0
aws apigateway get-resources --rest-api-id $API
{ "items": [ { "path": "/", "id": "e8kitthgdb" } ] }
この時点ではルートリソースのみですが、次のステップでリソースを追加します。
API でリソースを作成する
次の create-resource
コマンドを実行して、前のセクションで作成した API のリソース (DynamoDBManager
) を作成します。
$
aws apigateway create-resource --rest-api-id $API --path-part DynamoDBManager \ --parent-id
{ "path": "/DynamoDBManager", "pathPart": "DynamoDBManager", "id": "iuig5w", "parentId": "e8kitthgdb" }e8kitthgdb
応答内の ID を書き留めます。これは、作成した DynamoDBManager
リソースの ID です。
リソースに対する POST メソッドを作成する
次の put-method
コマンドを実行して、API の DynamoDBManager
リソースで POST
メソッドを作成します。
$
RESOURCE=
$iuig5w
aws apigateway put-method --rest-api-id $API --resource-id $RESOURCE \ --http-method POST --authorization-type NONE
{ "apiKeyRequired": false, "httpMethod": "POST", "authorizationType": "NONE" }
--authorization-type
パラメータに、このメソッドでは未認証リクエストがサポートされていることを意味する NONE
を指定します。この値はテスト用には適切ですが、本稼働時にはキーベースまたはロールベースのいずれかの認証を使用する必要があります。
Lambda 関数を POST メソッドの送信先に設定する
次のコマンドを実行して、Lambda 関数を POST
メソッドの統合ポイントとして設定します。これは、POST
メソッドエンドポイントの HTTP リクエストを行ったときに Amazon API Gateway が呼び出すメソッドです。このコマンドと他のコマンドは、アカウント
ID とリージョンを含む ARN を使用します。これらを変数に保存します (アカウント ID は、関数の作成に使用したロール ARN にあります)。
$
REGION=
$us-east-2
ACCOUNT=
$123456789012
aws apigateway put-integration --rest-api-id $API --resource-id $RESOURCE \ --http-method POST --type AWS --integration-http-method POST \ --uri arn:aws:apigateway:$REGION:lambda:path/2015-03-31/functions/arn:aws:lambda:$REGION:$ACCOUNT:function:LambdaFunctionOverHttps/invocations
{ "type": "AWS", "httpMethod": "POST", "uri": "arn:aws:apigateway:us-east-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-2:123456789012:function:LambdaFunctionOverHttps/invocations", "passthroughBehavior": "WHEN_NO_MATCH", "timeoutInMillis": 29000, "cacheNamespace": "iuig5w", "cacheKeyParameters": [] }
--integration-http-method
は、API Gateway が AWS Lambda との通信に使用するメソッドです。--uri
は、Amazon API Gateway がリクエストを送信できるエンドポイントの一意識別子です。
POST
メソッドのレスポンスおよび統合レスポンスの content-type
を、以下のように JSON に設定します。
-
次のコマンドを実行して、
POST
メソッドのレスポンスを JSON に設定します。これが、API メソッドが返すレスポンスのタイプになります。$
aws apigateway put-method-response --rest-api-id $API \ --resource-id $RESOURCE --http-method POST \ --status-code 200 --response-models application/json=Empty
{ "statusCode": "200", "responseModels": { "application/json": "Empty" } } -
次のコマンドを実行して、
POST
メソッドの統合レスポンスを JSON に設定します。これが、Lambda 関数が返すレスポンスのタイプになります。$
aws apigateway put-integration-response --rest-api-id $API \ --resource-id $RESOURCE --http-method POST \ --status-code 200 --response-templates application/json=""
{ "statusCode": "200", "responseTemplates": { "application/json": null } }注記 このコマンドの実行中にエラーが発生した場合は、レスポンステンプレートフィールドをエスケープ文字で囲むと、わかりやすくなります。テキスト
application/json=""
は、"{\"application/json"\":""\"\"}""
になります。
API をデプロイする
このステップでは、作成した API を prod
というステージにデプロイします。
$
aws apigateway create-deployment --rest-api-id $API --stage-name prod
{ "id": "20vgsz", "createdDate": 1539820012 }
API に呼び出しアクセス許可を付与する
Amazon API Gateway を使用して API を作成し、デプロイしたので、テストできます。まず、POST
メソッドに HTTP リクエストを送信したときに、Amazon API Gateway が Lambda 関数を呼び出すことができるようにアクセス許可を追加する必要があります。
これを行うには、Lambda 関数に関連付けられているアクセス権限ポリシーにアクセス権限を追加する必要があります。次の AWS Lambda add-permission
コマンドを実行して、Lambda 関数 (LambdaFunctionOverHttps
) を呼び出すアクセス権限を Amazon API Gateway サービスプリンシパル (apigateway.amazonaws.com
) に付与します。
$
aws lambda add-permission --function-name LambdaFunctionOverHttps \ --statement-id apigateway-test-2 --action lambda:InvokeFunction \ --principal apigateway.amazonaws.com \ --source-arn "arn:aws:execute-api:$REGION:$ACCOUNT:$API/*/POST/DynamoDBManager"
{ "Statement": "{\"Sid\":\"apigateway-test-2\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"apigateway.amazonaws.com\"},\"Action\":\"lambda:InvokeFunction\",\"Resource\":\"arn:aws:lambda:us-east-2:123456789012:function:LambdaFunctionOverHttps\",\"Condition\":{\"ArnLike\":{\"AWS:SourceArn\":\"arn:aws:execute-api:us-east-2:123456789012:mnh1yprki7/*/POST/DynamoDBManager\"}}}" }
テストを行うには、このアクセス権限を付与する必要があります (Amazon API Gateway に移動し、[Test] を選択して API メソッドをテストする場合は、このアクセス権限が必要です)。--source-arn
には、ステージ値としてワイルドカード文字 (*) を指定する (テスト用のみを表す) ことに注意してください。これにより、API をデプロイせずにテストできます。
関数と API が異なるリージョンにある場合、ソース ARN のリージョン識別子は、API のリージョンではなく、関数のリージョンと一致している必要があります。
次に、同じコマンドをもう一度実行しますが、今度は、Lambda 関数を呼び出すためのアクセス権限を、デプロイ済み API に付与します。
$
aws lambda add-permission --function-name LambdaFunctionOverHttps \ --statement-id apigateway-prod-2 --action lambda:InvokeFunction \ --principal apigateway.amazonaws.com \ --source-arn "arn:aws:execute-api:$REGION:$ACCOUNT:$API/prod/POST/DynamoDBManager"
{ "Statement": "{\"Sid\":\"apigateway-prod-2\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"apigateway.amazonaws.com\"},\"Action\":\"lambda:InvokeFunction\",\"Resource\":\"arn:aws:lambda:us-east-2:123456789012:function:LambdaFunctionOverHttps\",\"Condition\":{\"ArnLike\":{\"AWS:SourceArn\":\"arn:aws:execute-api:us-east-2:123456789012:mnh1yprki7/prod/POST/DynamoDBManager\"}}}" }
デプロイ済み API が Lambda 関数を呼び出すためのアクセス権限を持つように、このアクセス権限を付与します。--source-arn
には、API のデプロイ時に使用したステージ名である prod
を指定することに注意してください。
Amazon DynamoDB テーブルの作成
Lambda 関数が使用する DynamoDB テーブルを作成します。
DynamoDB テーブルを作成するには
-
DynamoDB コンソール
を開きます。 -
[Create table] を選択します。
-
次の設定でテーブルを作成します。
-
[Table name (テーブル名)] –
lambda-apigateway
-
[プライマリキー] –
id
(文字列)
-
-
[作成] を選択します。
HTTP リクエストを使用して関数をトリガーする
このステップでは、POST
メソッドのエンドポイントに HTTP リクエストを送信する準備ができています。Curl または Amazon API Gateway で提供されているメソッド (test-invoke-method
) のいずれかを使用できます。
リソース (DynamoDBManager
) のエンドポイントに HTTP POST
リクエストを送信するには、Amazon API Gateway の CLI コマンドを使用できます。Amazon API Gateway はデプロイ済みであるため、Curl
を使用して同じオペレーション用のメソッドを呼び出すことができます。
Lambda 関数では、DynamoDB テーブル内に項目を作成する create
オペレーションの使用がサポートされています。このオペレーションをリクエストするには、次の JSON を使用します。
例 create-item.json
{ "operation": "create", "tableName": "lambda-apigateway", "payload": { "Item": { "id": "1234ABCD", "number": 5 } } }
テスト入力を create-item.json
というファイルに保存します。test-invoke-method
Amazon API Gateway コマンドを実行して HTTP POST
メソッドリクエストをリソース (DynamoDBManager
) エンドポイントに送信します。
$
aws apigateway test-invoke-method --rest-api-id $API \ --resource-id $RESOURCE --http-method POST --path-with-query-string "" \ --body file://create-item.json
または、次の Curl コマンドを使用することもできます。
$
curl -X POST -d "{\"operation\":\"create\",\"tableName\":\"lambda-apigateway\",\"payload\":{\"Item\":{\"id\":\"1\",\"name\":\"Bob\"}}}" https://$API.execute-api.$REGION.amazonaws.com/prod/DynamoDBManager
Lambda 関数でサポートされている echo
オペレーション用のリクエストを送信するには、次のリクエストペイロードを使用できます。
例 echo.json
{ "operation": "echo", "payload": { "somekey1": "somevalue1", "somekey2": "somevalue2" } }
テスト入力を echo.json
というファイルに保存します。リクエストボディに前述の JSON を使用して、リソース (DynamoDBManager
) のエンドポイントに POST
メソッドの HTTP リクエストを送信する、Amazon API Gateway の test-invoke-method
CLI コマンドを実行します。
$
aws apigateway test-invoke-method --rest-api-id $API \ --resource-id $RESOURCE --http-method POST --path-with-query-string "" \ --body file://echo.json
または、次の Curl コマンドを使用することもできます。
$
curl -X POST -d "{\"operation\":\"echo\",\"payload\":{\"somekey1\":\"somevalue1\",\"somekey2\":\"somevalue2\"}}" https://$API.execute-api.$REGION.amazonaws.com/prod/DynamoDBManager
リソースのクリーンアップ
このチュートリアル用に作成したリソースは、保持する必要がなければ、削除できます。使用しなくなった AWS リソースを削除することで、AWS アカウントに請求される不要な料金が発生しないようにできます。
Lambda 関数を削除するには
-
Lambda コンソールの [Functions (関数)
] ページを開きます。 -
作成した関数を選択します。
-
[ Actions] で、[Delete ] を選択します。
-
[削除] を選択します。
実行ロールを削除するには
-
IAM コンソールのロールページ
を開きます。 -
作成した実行ロールを選択します。
-
[ロールの削除] を選択します。
-
[はい、削除します] を選択します。
API を削除するには
-
API Gateway コンソールの API ページ
を開きます。 -
作成した API を選択します。
-
[ Actions] で、[Delete ] を選択します。
-
[削除] を選択します。
DynamoDB テーブルを削除するには
-
DynamoDB コンソールのテーブルページ
を開きます。 -
作成したテーブルを選択します。
-
[削除] を選択します。
-
テキストボックスに
delete
を入力します。 -
[削除] を選択します。