次のステップでは、Amazon API Gateway(以降、API Gateway)を関数の前に追加していきます。 API GatewayはパブリックHTTPエンドポイントを公開します。このエンドポイントは、インターネット上の誰もが curlやウェブブラウザのようなHTTPクライアントでヒットできます。
API Gatewayのルートには、 Lambda proxy integrationを利用します。 これは、どのURLパスへのリクエストも、直接Lambda関数にプロキシされ、関数からのレスポンスがユーザーに返される動作となります。
lib/cdk-workshop-stack.ts
に戻り、APIエンドポイントを定義してLambda関数に関連付けましょう。
import { Stack, StackProps } from 'aws-cdk-lib';
import { LambdaRestApi } from 'aws-cdk-lib/aws-apigateway';
import { Runtime } from 'aws-cdk-lib/aws-lambda';
import { NodejsFunction } from 'aws-cdk-lib/aws-lambda-nodejs';
import { Construct } from 'constructs';
export class CdkWorkshopStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
// AWS Lambdaリソースを定義
const hello = new NodejsFunction(this, 'HelloHandler', {
runtime: Runtime.NODEJS_16_X,
entry: 'lambda/hello.ts',
});
// "hello" 関数をバックに持つAPI Gateway REST APIリソースを定義
new LambdaRestApi(this, 'Endpoint', {
handler: hello,
});
}
}
以上です。これで、すべてのリクエストをAWS Lambda関数にプロキシするAPI Gatewayが定義されました。
これをデプロイするとどうなるのか見てみましょう。
cdk diff
出力は次のようになります。
Stack CdkWorkshopStack
IAM Statement Changes
┌───┬─────────────────────┬────────┬───────────────────────┬──────────────────────────────────────────────────────────────────┬───────────────────────────────────────────────────────────────────┐
│ │ Resource │ Effect │ Action │ Principal │ Condition │
├───┼─────────────────────┼────────┼───────────────────────┼──────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────┤
│ + │ ${HelloHandler.Arn} │ Allow │ lambda:InvokeFunction │ Service:apigateway.amazonaws.com │ "ArnLike": { │
│ │ │ │ │ │ "AWS:SourceArn": "arn:${AWS::Partition}:execute-api:${AWS::Regi │
│ │ │ │ │ │ on}:${AWS::AccountId}:${EndpointEEF1FD8F}/${Endpoint/DeploymentSt │
│ │ │ │ │ │ age.prod}/*/*" │
│ │ │ │ │ │ } │
│ + │ ${HelloHandler.Arn} │ Allow │ lambda:InvokeFunction │ Service:apigateway.amazonaws.com │ "ArnLike": { │
│ │ │ │ │ │ "AWS:SourceArn": "arn:${AWS::Partition}:execute-api:${AWS::Regi │
│ │ │ │ │ │ on}:${AWS::AccountId}:${EndpointEEF1FD8F}/test-invoke-stage/*/*" │
│ │ │ │ │ │ } │
│ + │ ${HelloHandler.Arn} │ Allow │ lambda:InvokeFunction │ Service:apigateway.amazonaws.com │ "ArnLike": { │
│ │ │ │ │ │ "AWS:SourceArn": "arn:${AWS::Partition}:execute-api:${AWS::Regi │
│ │ │ │ │ │ on}:${AWS::AccountId}:${EndpointEEF1FD8F}/${Endpoint/DeploymentSt │
│ │ │ │ │ │ age.prod}/*/" │
│ │ │ │ │ │ } │
│ + │ ${HelloHandler.Arn} │ Allow │ lambda:InvokeFunction │ Service:apigateway.amazonaws.com │ "ArnLike": { │
│ │ │ │ │ │ "AWS:SourceArn": "arn:${AWS::Partition}:execute-api:${AWS::Regi │
│ │ │ │ │ │ on}:${AWS::AccountId}:${EndpointEEF1FD8F}/test-invoke-stage/*/" │
│ │ │ │ │ │ } │
└───┴─────────────────────┴────────┴───────────────────────┴──────────────────────────────────────────────────────────────────┴───────────────────────────────────────────────────────────────────┘
(NOTE: There may be security-related changes not in this list. See https://github.com/aws/aws-cdk/issues/1299)
Resources
[+] AWS::ApiGateway::RestApi Endpoint EndpointEEF1FD8F
[+] AWS::ApiGateway::Deployment Endpoint/Deployment EndpointDeployment318525DA5f8cdfe532107839d82cbce31f859259
[+] AWS::ApiGateway::Stage Endpoint/DeploymentStage.prod EndpointDeploymentStageprodB78BEEA0
[+] AWS::ApiGateway::Resource Endpoint/Default/{proxy+} Endpointproxy39E2174E
[+] AWS::Lambda::Permission Endpoint/Default/{proxy+}/ANY/ApiPermission.CdkWorkshopStackEndpoint018E8349.ANY..{proxy+} EndpointproxyANYApiPermissionCdkWorkshopStackEndpoint018E8349ANYproxy747DCA52
[+] AWS::Lambda::Permission Endpoint/Default/{proxy+}/ANY/ApiPermission.Test.CdkWorkshopStackEndpoint018E8349.ANY..{proxy+} EndpointproxyANYApiPermissionTestCdkWorkshopStackEndpoint018E8349ANYproxy41939001
[+] AWS::ApiGateway::Method Endpoint/Default/{proxy+}/ANY EndpointproxyANYC09721C5
[+] AWS::Lambda::Permission Endpoint/Default/ANY/ApiPermission.CdkWorkshopStackEndpoint018E8349.ANY.. EndpointANYApiPermissionCdkWorkshopStackEndpoint018E8349ANYE84BEB04
[+] AWS::Lambda::Permission Endpoint/Default/ANY/ApiPermission.Test.CdkWorkshopStackEndpoint018E8349.ANY.. EndpointANYApiPermissionTestCdkWorkshopStackEndpoint018E8349ANYB6CC1B64
[+] AWS::ApiGateway::Method Endpoint/Default/ANY EndpointANY485C938B
Outputs
[+] Output Endpoint/Endpoint Endpoint8024A810: {"Value":{"Fn::Join":["",["https://",{"Ref":"EndpointEEF1FD8F"},".execute-api.",{"Ref":"AWS::Region"},".",{"Ref":"AWS::URLSuffix"},"/",{"Ref":"EndpointDeploymentStageprodB78BEEA0"},"/"]]}}
追加したコードにより、10個の新しいリソースがスタックに追加されることがわかります。
デプロイする準備が整いました。
cdk deploy
デプロイが完了すると、次の内容が出力されているはずです。
CdkWorkshopStack.Endpoint8024A810 = https://xxxxxxxxxx.execute-api.us-east-1.amazonaws.com/prod/
これは、API Gatewayコンストラクトによって自動的に追加されるstack outputであり、API GatewayエンドポイントのURLが含まれます。
次に、このエンドポイントを curl
で叩いてみましょう。 URLをコピーして実行します。(プレフィックスとリージョンは異なる可能性があります)
curlをインストールしていない場合は、WebブラウザでこのURLにアクセスしてみてください。
curl https://xxxxxxxxxx.execute-api.us-east-1.amazonaws.com/prod/
出力は次のようになります。
Hello, CDK! You've hit /
Webブラウザでも確認できます。
この出力がされていれば、アプリは正常に動作しています。
API Gatewayから5xxエラーを受け取った場合、次の2つの問題のいずれかが該当しています。
statusCode
, body
, header
フィールドが含まれているか確認してください。
(参照: Lambdaのhandler関数のコード)お疲れさまでした! 次の章では再利用可能な独自のコンストラクトを作成します。