AWS CDKでApi Gatewayを設定しLambdaから読み出してローカル実行を行ったメモ


概要

前回はLambda Layerを導入した。
今回はAPI Gatewayを使ってHTTPでLambda Functionsを叩けるようにする。

ソースコード

やること

  • ローカル実行
  • POSTのテスト
  • GETでパラメータを取得できることのテスト

やらないこと

デプロイ

コード

GET用のFunctionsの追加

src/lambda/handlers/get-echo.ts
import { APIGatewayProxyHandler } from 'aws-lambda';
import * as response from '../utilities/reponse';

export const echoHandler: APIGatewayProxyHandler = async (event) => {
  const { httpMethod, path, pathParameters } = event;
  if (httpMethod !== 'GET') {
    throw new Error(`getMethod only accept GET method, you tried: ${httpMethod}`);
  }
  console.log('received:', JSON.stringify(event));

  // Get id from pathParameters from APIGateway because of `/{id}` at template.yml
  const params = pathParameters;
  if (!params || !params.id) {
    return response.badRequest('parameter is required')
  }
  const { id } = params;
  const res = response.ok(id);
  console.log(`response from: ${path} statusCode: ${res.statusCode} body: ${res.body}`);
  return res;
};

Stack

lib/sample-stack.ts
import * as cdk from '@aws-cdk/core';
import * as lambda from '@aws-cdk/aws-lambda';
import { NodejsFunction } from '@aws-cdk/aws-lambda-nodejs';
+ import * as apigateway from '@aws-cdk/aws-apigateway'
import { NODE_LAMBDA_LAYER_DIR } from './process/setup';

export class SampleStack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);
-   new NodejsFunction(this, 'hello', {
+   const helloFunction = new NodejsFunction(this, 'hello', {
      runtime: lambda.Runtime.NODEJS_14_X,
      entry: 'src/lambda/handlers/hello.ts',
      functionName: 'kotahello',
      handler: 'lambdaHandler'
    });

    const nodeModulesLayer = new lambda.LayerVersion(this, 'NodeModulesLayer',
      {
        code: lambda.AssetCode.fromAsset(NODE_LAMBDA_LAYER_DIR),
        compatibleRuntimes: [lambda.Runtime.NODEJS_14_X]
      }
    );

    new NodejsFunction(this, 'test', {
      runtime: lambda.Runtime.NODEJS_14_X,
      entry: 'src/lambda/handlers/test.ts',
      functionName: 'kotatest',
      bundling: {
        externalModules: [
          'aws-sdk', // Use the 'aws-sdk' available in the Lambda runtime
          'date-fns', // Layrerに入れておきたいモジュール
        ],
        define: { // Replace strings during build time
          'process.env.API_KEY': JSON.stringify(`\\"${'xxx-xxx'}\\"`), // バグってそう.エスケープしないとInvalid define valueのエラー
        },
      },
      layers: [nodeModulesLayer],
    });
+    const echoFunction = new NodejsFunction(this, 'echo', {
+      runtime: lambda.Runtime.NODEJS_14_X,
+      entry: 'src/lambda/handlers/get-echo.ts',
+      functionName: 'get-echo',
+      handler: 'echoHandler'
+    });
+    const api = new apigateway.RestApi(this, 'ServerlessRestApi', { cloudWatchRole: false });
+    api.root.addMethod('POST', new apigateway.LambdaIntegration(helloFunction));
+    api.root.addResource('{id}').addMethod('GET', new apigateway.LambdaIntegration(echoFunction));
  }
}

package.json

package.json
{
  "name": "myapp",
  "version": "0.1.0",
  "scripts": {
    "build": "tsc",
    "watch": "tsc -w",
    "test": "jest",
    "cdk": "cdk",
    "bundle": "cdk synth && cdk synth > cdk.out/template.yaml",
    "localinvoke": "cd cdk.out && sam.cmd local invoke testAF53AC38 --no-event",
+    "dev-server": "cd cdk.out && sam.cmd local start-api"
  },
  "devDependencies": {
    "@aws-cdk/assert": "^1.93.0",
+    "@aws-cdk/aws-apigateway": "^1.93.0",
    "@aws-cdk/aws-lambda-nodejs": "^1.93.0",
    "@aws-cdk/core": "^1.93.0",
    "@types/aws-lambda": "^8.10.72",
    "@types/fs-extra": "^9.0.8",
    "@types/jest": "^26.0.10",
    "@types/node": "10.17.27",
    "aws-cdk": "^1.93.0",
    "esbuild": "^0.9.0",
    "fs-extra": "^9.1.0",
    "jest": "^26.4.2",
    "source-map-support": "^0.5.19",
    "ts-jest": "^26.2.0",
    "ts-node": "^9.0.0",
    "typescript": "~3.9.7"
  },
  "dependencies": {
    "date-fns": "^2.19.0"
  }
}

結果

  • npm run dev-server
  • getもpostも想定通りの結果を返してくれた


参考

AWS CDKでAPI Gateway+Lambdaを作成する際のベストなスタック構成について
API Gatewayのローカルでの実行
サーバーレスをこれから始める方へ!「形で考えるサーバーレス設計」のCDKテンプレート(web/mBaaS編)を試して解説してみた
AWS CDKでTypeScriptで書かれたLambdaにLambda ProxyなREST APIを追加する
@aws-cdk/aws-apigateway module