別サイト
に書いていたのだけどサ終してしまったので移行した記事その4
2019/03/09のもの
サーバレスでDynamoDBにデータを入れる
EC2インスタンスを立てたら負けってどこかに書いてあったのでなしでどうにかやってみる
DynamoDBにテーブルを作成
なんでもいいのでIDとアドレスを入れるやつを適当に作る
テーブル名はregisterにする
LambdaからDynamoDBを操作するIAMを作成
Lambdaで使うためのIAMを作る
名前は
lambda-dynamodb-execution-role
とでもして権限を付与。
Lambdaを作成
テーブルに対して検索と投入をするLambdaを作成
ブランクで作成し、Node.js 8.10を選択
名前は適当にregisterInsertFuncとregisterSelectFuncとでもする
実行ロールは先程作成したやつを設定
## insert
var aws = require('aws-sdk');
var dynamo = new aws.DynamoDB.DocumentClient({region: 'ap-northeast-1'});
exports.handler = (event, context, callback) => {
console.log("event:", event);
dynamo.put({
"TableName": "register",
"Item": {
"event_id": event.event_id,
"address": event.address
}
}, function( err, data ) {
console.log("dynamo_err:", err);
context.done(null, data);
});
};
## select
var aws = require('aws-sdk');
var dynamo = new aws.DynamoDB.DocumentClient({region: 'ap-northeast-1'});
exports.handler = function (event, context) {
var params = {
TableName : 'register',
KeyConditionExpression: "event_id = :event_id and address = :address",
ExpressionAttributeValues: {
":event_id": event.event_id,
":address": event.address
}
};
dynamo.query(params, function(err, data) {
console.log("dynamo_data:", data);
console.log("dynamo_err:", err);
context.done(null, data);
});
};
テスト用のパラメータは下記
{
"event_id": "101",
"address": "hogehuga@hoge.jp"
}
API Gatewayの作成
Lambdaを呼び出すためのAPI Gatewayを作成する
/eventリソースを作成してメソッドの作成でGET,POSTを作成する(PUTもあるが気にしない)
{
"event_id": "$input.params('event_id')",
"address": "$input.params('address')"
}
/eventリソースに対してアクションからCORSの有効化をする
ここまで作業できたらAPIのデプロイを行って反映
一旦確認
ここまできたらAPI GatewayのURLが生成されるのでcurl等で確認ができる
$ curl -X GET https://[API GatewayのURL]\?event_id\=102\&address\=hogehoge
{"Items":[],"Count":0,"ScannedCount":0}
$ curl -X POST https://[API GatewayのURL]\?event_id\=102\&address\=hogehogehoge
{}
S3にコンテンツ配置
S3からAPI Gatewayを呼び出すためにhtmlを置く
event-registerというバケットを適当につくってトップにindex.htmlを配置
API Gatewayからライブラリをダウンロードして配置ってのもあったけどjQueryだけでいけたのでそっちにしてみた
PUTメソッドはなんかうまく動かなかったので諦め。。。(PUTメソッドがあったのはそのため)
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>API test</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
</head>
<body>
<input type="text" id="addId" value="102" />
<input type="text" id="addAddress" value="hogehogehoge" />
<button id="add">追加</button>
<br>
<input type="text" id="searchId" value="102" />
<input type="text" id="searchAddress" value="hogehogehoge" />
<button id="search">検索</button>
<script type="text/javascript">
$('#add').click(function(){
var addId = $('#addId').val()
var addAddress = $('#addAddress').val()
$.ajax({
url: "https://[API GatewayのURL]?event_id=" + addId + "&address=" + addAddress,
type: 'POST',
crossDomain: true,
dataType: 'json',
contentType: "application/json",
success: function (data) {
console.info(data);
}
});
});
$('#search').click(function(){
var searchId = $('#searchId').val()
var searchAddress = $('#searchAddress').val()
$.ajax({
url: "https://[API GatewayのURL]?event_id=" + searchId + "&address=" + searchAddress,
type: 'GET',
crossDomain: true,
dataType: 'json',
contentType: "application/json",
success: function (data) {
console.info(data);
}
});
});
</script>
</body>
</html>
CloudFront経由でS3へアクセス
CreateDistributionでS3のevent-registerを指定
- Restrict Bucket AccessをYes
- Origin Access IdentityをCreate a New Identity
- Grant Read Permissions on BucketをYes
に設定して作成
S3のバケットポリシーが更新されているのを確認してアクセスコントロールからEveryOneの権限をoffにする
これでCloudFront経由からのみS3にアクセスできるようになった
https://[CloudFrontで作成したURL]/index.html
で先程と同じ画面が出れば成功
感想
実際書いてみるとそんなに作業はないけど結構ハマった。。。
特にPUTメソッドのときだけSameオリジンポリシー制約にハマって結局わからなかった。。。
これが作成できると何ができるのって考えると
例えば事前登録サイトとかぐらいならhtmlさえちゃんと作ればだいたい作れそうだなーと思った
そうなるとインスタンス立ててサーバエンジニアが色々やることもなくてハッピーかな