LoginSignup
2
1

More than 3 years have passed since last update.

AWS+NodeJSでサーバレスな環境構築③

Last updated at Posted at 2020-01-04

はじめに

前回の記事ではDynamoDBのテーブルと項目作成、Lambda関数で使うロールやインラインポリシーの設定を行いました。今回はその続きで、API Gateway(REST APIでCRUD実装)をトリガーにし、Lambda(NodeJS)関数呼び出して、DynamoDBに参照や更新をできるようにします。
表現等が不適切の場合はご指摘いただければ、幸いです。
※サーバレスに関してよくわからない方は、こちらをご覧いただければと思います。

アーキテクチャ図

serverless.png

流れ

  • ソースで直接(Api gatewayを使わず)参照や更新ができるかを確認
  • POST(ユーザーの登録)
    • domain.com/users/{id}
  • DELETE(対象ユーザーの削除)
    • domain.com/users/{id}
  • GET(全ユーザーの取得)
    • domain.com/users
  • PATCH(対象ユーザーの更新)
    • domain.com/users/{id}

ソースで直接(Api gatewayを使わず)参照や更新ができるかを確認

まずはLambda(NodeJS)でDynamoDBテーブルが参照・更新できるか確認
Lambdaダッシュボード>関数の作成>一から作成>以下の通り入力>関数の作成ボタン
※既存のロール設定は前回の記事で作成したものを使用しています。
スクリーンショット 2020-01-03 19.43.16.png

データの参照ができるよう、ソース編集
こちらのリファレンスを参考にしました。

index.js
'use strict';

const AWS = require('aws-sdk');
const myRegion = "us-east-2";

AWS.config.update({ region: myRegion});

exports.handler = async (event, context) => {
  const documentClient = new AWS.DynamoDB.DocumentClient({ region: myRegion});

  //読込用のデータ
  const params1 = {
    TableName: "Users",
    Key: {
      id: "01"
    }
  };
  //書込用のデータ
  const params2 = {
    TableName: "Users",
    Item: {
      id: "02",
      firstname: "first02",
      lastname: "last02"
    }
  };

  try {
    const readData = await documentClient.get(params1).promise();
    const writeData = await documentClient.put(params2).promise();
    console.log(readData);
    console.log(writeData);
  } catch (err) {
    console.log(err);
  }
};

⚠️ 必ず、DynamoDBとLambdaは同じリージョンで作成するように気をつける。また上記ソースのmyRegion変数値も合わせるように気をつける。いずれが満たない場合、AccessDeniedExceptionという意味不明なエラーが発生する可能性があります。

テストイベントの設定>テストボタン>取得結果が表示されれば、OK
スクリーンショット 2020-01-03 19.58.10.png

DynamoDBにデータ作成されていることを確認
ちなみに、params2でidをそのまま、firstnameやlastnameを変更すると更新される仕様です。
スクリーンショット 2020-01-03 20.00.54.png

API Gatewayトリガー追加と設定

API Gatewayダッシュボード>APIを作成ボタン>REST APIの構築ボタン(Privateじゃない方)
以下のように入力>APIの作成ボタン
スクリーンショット 2020-01-03 20.32.20.png

エッジ最適化について(AWS公式より引用)

エッジ最適化 API は、API ゲートウェイによって作成および管理される CloudFront ディストリビューション経由でアクセスするエンドポイントです。以前は、エッジ最適化 API は、API ゲートウェイを使用して API を作成する際のデフォルトオプションでした。

参考記事
0からREST APIについて調べてみた
エッジ最適化について説明

リクエスト、レスポンスマッピングのモデルを作成及び設定

参考
モデル名、コンテンツタイプ、スキーマ(ソース)を設定します。
スクリーンショット 2020-01-03 21.41.42.png

スキーマのソース
{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "title": "UsersInputModel",
  "type": "object",
  "properties": {
      "id": {"type": "string"},
      "firstname": {"type": "string"},
      "lastname": {"type": "string"}
  }
}

アクション>リソースの作成
リソースは2つ作成します。
スクリーンショット 2020-01-03 21.13.48.png
スクリーンショット 2020-01-03 21.15.55.png

POSTメソッド実装(ユーザーの登録)

ここではAPI GatewayでPOSTメソッドを作成して、レコードが登録されるかを確認する。

API Gatewayと紐付けるLambda関数を作成と設定

関数名はputUsersで、その他の設定は前回と一緒(察して)(冒頭のLambda関数作成のスクリーンショット参照)

以下のソースを貼り付けます。
DynamoDBの構成に関しては、こちらの記事を参考にしてください。(DynamoDBテーブルの作成部分)

index.js
'use strict';
const AWS = require('aws-sdk');
const myRegion = "us-east-2";

AWS.config.update({ region: myRegion});

exports.handler = async (event, context) => {
  const documentClient = new AWS.DynamoDB.DocumentClient({ region: myRegion});

  let responseBody = "";
  let statusCode = 0;

  const { id, firstname, lastname } = JSON.parse(event.body);

  const params = {
    TableName: "Users",
    Item: {
      id: id,
      firstname: firstname,
      lastname: lastname
    }
  };

  try {
    const data = await documentClient.put(params).promise();
    responseBody = JSON.stringify(data);
    statusCode = 201;
  } catch (err) {
    responseBody = `Unable to put user ${err}`;
    statusCode = 403;
  }

  const response = {
    statusCode: statusCode,
    headers: {
       "Content-Type": "application/json"
    },
    body: responseBody
  };

  return response;
}

POSTメソッド作成と設定

アクション>メソッドの作成
スクリーンショット 2020-01-03 21.24.17.png

メソッドリクエストの設定
モデルの追加には上記の作成したモデルを追加する
スクリーンショット 2020-01-03 21.46.26.png

API Gatewayで確認テスト

下の方にテストボタンあるので、それを押すとテスト結果(ログも含めて)画面右側に表示されると思います。
スクリーンショット 2020-01-03 22.12.05.png

スクリーンショット 2020-01-03 22.23.42.png

リクエスト本文
{
    "id": "03",
    "firstname": "first03",
    "lastname": "last03"
}

テストステータスで201が返ってこれば、成功みたいです。
⚠️ ちなみに本来DynamoDBテーブルにない項目論理名(例えばfirstnameではなく、あえてnickname)をリクエスト本文に設定された場合、問題なくテスト処理は実行されます。対象のレコードfirstnameには空白が入る仕様になっています。

DynamoDBテーブルにレコードが作成されていることを確認
スクリーンショット 2020-01-03 22.27.09.png

to be continued

ちょっと長くなりそうなので、続きを次回出します。
あとはDELETE(対象ユーザーの削除), GET(全ユーザーの取得) PATCH(対象ユーザーの更新)のメソッドを作成して、最後までCRUD機能を実装していきます。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1