サーバレスフレームワークでCRUDを作っていきます
使うツール
- serverless framework
サーバレスフレームワークを使うとyamlファイルで開発環境が作れるので、人的なミスを減らせてコード管理が楽になります。
使用するサービス
- iam
- lambda
- api gateway
- dynamodb
テーブルのスキーマ
id: String
name: String
text: String
date: Number
読み取り機能
documentClientのgetメソッドを使います
Dynamo.js
const AWS = require('aws-sdk');
const documentClient = new AWS.DynamoDB.DocumentClient();
const Dynamo = {
get: async (id, TableName) => {
const params = {
TableName,
Key: { id }
};
const data = await documentClient
.get(params)
.promise();
if (!data || !data.Item) {
throw Error(`${TableName}に${id}がありません`);
}
return data.Item;
}
};
module.exports = Dynamo;
getKeijibanPosts.js
const Responses = require('../common/API_Responses');
const Dynamo = require('./common/Dynamo');
const TableName = process.env.tableName;
exports.handler = async (event, context, callback) => {
console.log('event', event);
if (!event.pathParameters || !event.pathParameters.id) {
// idが渡されて無い
return Responses._400({ message: 'idを指定してください' });
}
const id = event.pathParameters.id;
const res = await Dynamo.get(id, TableName).catch(err => {
console.log('error =', err);
return null
});
// idが存在しない時
if (!res) {
return Responses._400({ message: '指定したidのデータは存在しません' });
}
return Responses._200(res);
}
serverless.yml
service: kani-keijiban
frameworkVersion: '2'
provider:
name: aws
runtime: nodejs12.x
stage: test
region: us-east-1
environment:
tableName: ${self:custom.tableName}
iamRoleStatements:
- Effect: Allow
Action:
- dynamodb:GetItem
- dynamodb:PutItem
- dynamodb:UpdateItem
- dynamodb:DeleteItem
Resource:
!GetAtt KaniKeijibanDB.Arn
custom:
tableName: KaniPosts
functions:
getKeijibanPosts:
handler: lambdas/endpoints/getKeijibanPosts.handler
events:
- http:
path: api/posts/{id}
method: get
cors: true
resources:
Resources:
KaniKeijibanDB:
Type: AWS::DynamoDB::Table
Properties:
TableName: ${self:custom.tableName}
AttributeDefinitions:
- AttributeName: id
AttributeType: S
KeySchema:
- AttributeName: id
KeyType: HASH
ProvisionedThroughput:
ReadCapacityUnits: 5
WriteCapacityUnits: 5
書き込み機能
documentClientのputメソッドを使います
serverless.ymlのfuncitonsにコードを追加
createKeijibanPosts:
handler: lambdas/endpoints/createKeijibanPosts.handler
events:
- http:
path: api/posts
method: post
cors: true
Dynamo.jsのgetメソッドの下に追加
put: async (item, TableName) => {
if (!item.id) {
throw Error('idがありません');
}
const params = {
TableName,
Item: item
};
const data = await documentClient
.put(params)
.promise()
return data;
}
createKeijibanPosts.jsを新たに作成
const Responses = require('../common/API_Responses');
const Dynamo = require('../common/Dynamo');
const TableName = process.env.tableName;
exports.handler = async (event, context, callback) => {
console.log('event', event);
const item = JSON.parse(event.body);
const res = await Dynamo.put(item, TableName).catch(err => {
console.log('error =', err);
return null
});
// 作成に失敗した時
if (!res) {
return Responses._400({ message: '作成に失敗しました' });
}
return Responses._200(res);
}
これで追加機能ができました。
更新機能を作成
documentClientのupdateメソッドを使います
serverless.ymlのfunctionsに追加
updateKeijibanPosts:
handler: lambdas/endpoints/updateKeijibanPosts.handler
events:
- http:
path: api/posts/{id}
method: put
cors: true
Dynamo.jsのputメソッドの下に追加
※(text
がlambdaの予約語と被ってしまったので'#tx'
でプレースホルダーを使ってます)
update: async ({ id, tableName, updateKey, updateValue }) => {
const params = {
TableName: tableName,
Key: {
id
},
UpdateExpression: `set #tx = :updateValue`,
ExpressionAttributeNames: {
'#tx': updateKey
},
ExpressionAttributeValues: {
':updateValue': updateValue
},
};
const res = await documentClient
.update(params)
.promise();
return res;
},
updateKeijibanPosts.jsを新たに作成
const Dynamo = require('../common/Dynamo');
const Responses = require('../common/API_Responses');
const TableName = process.env.tableName;
exports.handler = async (event, context, callback) => {
const id = event.pathParameters.id;
// return the data
const { text } = JSON.parse(event.body);
const updateParams = {
id,
tableName: TableName,
updateKey: 'text',
updateValue: text
};
const res = await Dynamo.update(updateParams);
console.log('res = ', res);
return Responses._200({});
}
これで更新機能ができました。
削除機能
documentClientのdeleteメソッドを使います
serverless.ymlのfunctionsに追加
deleteKeijibanPosts:
handler: lambdas/endpoints/deleteKeijibanPosts.handler
events:
- http:
path: api/posts/{id}
method: delete
cors: true
Dynamo.jsのupdateメソッドの下に追加
delete: async (id, TableName) => {
const params = {
TableName,
Key: { id }
};
const data = await documentClient
.delete(params)
.promise();
return data;
},
deleteKeijibanPosts.jsを新たに作成
const Dynamo = require('../common/Dynamo');
const Responses = require('../common/API_Responses');
const TableName = process.env.tableName;
exports.handler = async (event, context, callback) => {
const id = event.pathParameters.id;
// return the data
const res = await Dynamo.delete(id, TableName);
console.log('res = ', res);
return Responses._200(res);
}
動作確認
まとめ
簡単なCRUD操作を知ることができた。
serverless frameworkのenvironmentに変数を書くとlambdaのprocess.envから読み込むことができる。