BETA

CloudFront経由でDynamoDBのデータを更新する

投稿日:2019-03-09
最終更新: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": "[email protected]"  
}

API Gatewayの作成

Lambdaを呼び出すためのAPI Gatewayを作成する
/eventリソースを作成してメソッドの作成でGET,POSTを作成する(PUTもあるが気にしない)

  • メソッドリクエストにパラメータ
  • 統合リクエストにマッピングテンプレート
  • メソッドレスポンスのコンテンツタイプをapplication/json;charset=UTF-8
    をそれぞれ設定

{  
    "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>

こんな感じの画面が出てボタンを押してエラーがでなければOK

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さえちゃんと作ればだいたい作れそうだなーと思った
そうなるとインスタンス立ててサーバエンジニアが色々やることもなくてハッピーかな
(仕事なくなるけど)

技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
駆け出しエンジニアからエキスパートまで全ての方々のアウトプットを歓迎しております!
or 外部アカウントで 登録 / ログイン する
クランチについてもっと詳しく

この記事が掲載されているブログ

@sireikanの技術ブログ

よく一緒に読まれる記事

0件のコメント

ブログ開設 or ログイン してコメントを送ってみよう
目次をみる
技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
or 外部アカウントではじめる
10秒で技術ブログが作れます!