AWS CDK - #2 Lambda + OpenAPI(Swagger)でAPIを作る

今回は、OpenAPI(Swagger)で作成したAPI定義からAPIを構築し、そのAPIから呼び出されるLambdaを定義してデプロイしていきます。

一連の記事で作成したプロジェクトは以下にコミットされており、ブランチと記事番号が連動しています。

github.com

開発環境を整える

nomunomu0504.dev

1章でCDKプロジェクトを作成しましたが、ベースプロジェクトを作成したまでなので、Lint、Prettierなどはインストールされておらず、tsconfig.jsonなどもデフォルトのままとなっています。

これだと、開発していくのには少しつらい状態となっています。

そのため、tsconfig.jsonの修正、LintやPrettierなどをインストールして開発環境を整えていきたいと思います。

tsconfig.jsonの修正

tsconfig.jsonに以下の記述を追加します。追加する場所は typeRoots の下辺りで大丈夫です。

"baseUrl": "./",
"paths": {
  "~/*": ["./*"]
}

この定義を追加することによって、他ファイルを参照(import)する際に、絶対パスを記載しなくても、以下のように省略した形で参照することができます。

import { Component } from "~/src/components"

Linterのインストール

今回のプロジェクトでは eslint をインストールします。

npm install --save-dev eslint

インストールが完了したら、eslintの設定ファイルをいくつか作成します。

  • .eslintignore
  • .eslintrc.js
  • tsconfig.eslint.json

.eslintignore

今回は、typescriptをベースに開発を進めるため、.jsのファイルは一律で全てeslintの対象外とします。

node_modules
*.js

.eslintrc.js

構文エラーやコーディング規約を細かく定義することができます。

/**
 * ESLint Configuration
 */
/** @type {import('@typescript-eslint/experimental-utils').TSESLint.Linter.Config} */
const config = {
  root: true,
  extends: ["next", "next/core-web-vitals", "prettier"],
  parserOptions: {
    sourceType: "module",
    project: "./tsconfig.eslint.json",
  },
  rules: {
    // custom
    "react/display-name": "off",
    "@next/next/no-img-element": "off",
  },
};

module.exports = config;

tsconfig.eslint.json

TypeScriptにeslintを適用する際に、どのファイルまで適用するのか、どんなルールを適用するのか。などTSファイルへのlint設定を記載するためのファイルになります。

特に細かい設定が不要の場合には、tsconfig.json をExtendsして終わります。

{
  "extends": "./tsconfig.json"
}

OpenAPIでAPI定義を作る

OpenAPIについては今回は割愛します(どっかのタイミングで記事書きます...)

VSCodeにOpenAPIの定義ファイルを作成するために役立つプラグインがいくつかあるので、インストールしておきます。

プラグイン 概要
Swagger Viewer 書いているAPI定義をリアルタイムで確認することができます。
openapi-lint OpenAPIのドキュメント検証や静的解析を行ってくれます。
OpenAPI(Swagger) Editor 定義内のPathやComponentsをサイドバーに表示してくれます。あと、クリックすることで該当箇所まで飛ぶことができます。

OpenAPIドキュメントはYaml形式で記載します。

今回は以下を満たすようなAPIをデプロイしてみたいと思います。

Method Path 概要
GET /users ユーザー一覧をJSON形式で返却する
GET /users/<id> 特定のユーザーIDの情報をJSON形式で返却する

OpenAPIドキュメントは以下のようになります。

github.com

APIから呼び出されるLambdaを定義する

今回作成するLambdaは、APIパスに {id} が含まれていなかったら、ユーザー情報を全件返す。含まれていたら特定のユーザー情報のみを返す。という挙動を取るようにします。

※ ただし、今回の章ではDB等をつなぎ込んでいないため、Lambdaからハードコードされた情報を返却するものとします。

Lambda本体の処理

github.com

定義したAPIをCDKからデプロイする

デプロイするために必要な記述は、ざっくり分けると、今回は2つに分類されます。

  1. Lambdaの詳細設定(割当メモリや権限ロールなど)

  2. APIGateway・Lambdaのデプロイと紐付け

Lambdaの詳細設定は、Lambdaのデプロイタスクで記述します。

APIGateway・Lambdaのデプロイ・Integration設定などは、Stackタスクで記述します。

Lambdaデプロイタスク

github.com

APIGateway・Lambdaのデプロイと紐付け

github.com

package.jsonのnpm script

それぞれの記述が完了したら、デプロイ作業となります。毎回コマンドをcdkコマンドを打つのがめんどうなので、npm scriptに記述して、npm runコマンドから実行できるようにします。

github.com

初回デプロイ時には、1度だけ `npm run cdk-bootstrap` を実行する必要があります。これは、CDKからAWSリソースをデプロイするために必要な初期設定を行うものです。一度実行すれば、同じプロジェクトでは行う必要はありません。
aws-cdk-articles/cdk-project on  02-apigateway [!?] is 📦 v0.1.0 via  v16.5.0 on ☁️  (ap-northeast-1) took 6s 
❯ npm run cdk-bootstrap

> cdk-project@0.1.0 cdk-bootstrap
> cdk bootstrap --toolkit-stack-name="CDKToolKit-Aws-Cdk-Articles" --qualifier="nomunomu"

 ⏳  Bootstrapping environment aws://<account_id>/ap-northeast-1...
Trusted accounts for deployment: (none)
Trusted accounts for lookup: (none)
Using default execution policy of 'arn:aws:iam::aws:policy/AdministratorAccess'. Pass '--cloudformation-execution-policies' to customize.
CDKToolKit-Aws-Cdk-Articles: creating CloudFormation changeset...
 ✅  Environment aws://<account_id>/ap-northeast-1 bootstrapped.

bootstrapが成功したら、 npm run cdk-deploy でデプロイを実施します。

aws-cdk-articles/cdk-project on  02-apigateway [!?] is 📦 v0.1.0 via  v16.5.0 on ☁️  (ap-northeast-1) took 1m39s 
❯ npm run cdk-deploy   

> cdk-project@0.1.0 cdk-deploy
> cdk deploy --all --require-approval never -c @aws-cdk/core:bootstrapQualifier="nomunomu"

Bundling asset userApiGatewayStack/userLambdaTask/userLambda/Code/Stage...

  cdk.out/bundling-temp-bbe178953cbd61a260ba383919e8eadef0a095ac489cc1ebdc1ae5637fe58a67/index.js       83.9kb
  cdk.out/bundling-temp-bbe178953cbd61a260ba383919e8eadef0a095ac489cc1ebdc1ae5637fe58a67/index.js.map  170.8kb

⚡ Done in 14ms

✨  Synthesis time: 3.85s

userApiGatewayStack: deploying...
[0%] start: Publishing 046acb00a433a1174b6a7f44cbffc70d7f09c3a41c796983b2ad3f454e2ab8e1:current_account-current_region
[0%] start: Publishing 1124ef301c2a15335d3a4e14c9470d0d306fa8e087def44d48a34781c486a25b:current_account-current_region
[50%] success: Published 1124ef301c2a15335d3a4e14c9470d0d306fa8e087def44d48a34781c486a25b:current_account-current_region
[100%] success: Published 046acb00a433a1174b6a7f44cbffc70d7f09c3a41c796983b2ad3f454e2ab8e1:current_account-current_region
userApiGatewayStack: creating CloudFormation changeset...

 ✅  userApiGatewayStack

✨  Deployment time: 101.62s

Outputs:
userApiGatewayStack.userApiEndpointA0937F0C = https://bcbay2xsob.execute-api.ap-northeast-1.amazonaws.com/development/
Stack ARN:
arn:aws:cloudformation:ap-northeast-1:<account_id>:stack/userApiGatewayStack/b373b0d0-1df5-11ed-b42a-0e77075d7afd

✨  Total time: 105.46s

無事デプロイが完了すると、APIのエンドポイントが払い出されます。今回はこちら

https://bcbay2xsob.execute-api.ap-northeast-1.amazonaws.com/development/

このエンドポイントに以下2つのAPIが存在しています。

  • Userの全件取得

https://bcbay2xsob.execute-api.ap-northeast-1.amazonaws.com/development/users

  • 特定のUserを取得

https://bcbay2xsob.execute-api.ap-northeast-1.amazonaws.com/development/users/1

それぞれで、レスポンスが返却されれば、2章は完了となります。