【NodeJS】AWS Lambda+APIGateway+DynamoDBでTODOアプリを作成


はじめに

サーバーレスを趣味で始めてみたので、勉強がてらAWS Lambda+APIGateway+DynamoDBでTODOアプリを作成し始めました。
個人のメモとして、サーバー側とクライアント側での処理を記事にまとめます。(まだ作成途中です)

概要

Lambdaで使用する言語はNode
DynamoDBはidとtodoという項目のみを持ちます。
テーブル名は「todoTable」
今回は、GETとPOSTのみを実装します。

Lambdaで関数作成

本来であれば1つの関数にまとめたかったのですが、GETメソッドであることをLambdaに渡す方法がわからず、ひとまず関数を分けました。

まずはGETメソッドから。
単純に全てのカラムを取得します。(本来はあまりscanは使わない方がいいらしいが)

const AWS = require('aws-sdk')
const dynamo = new AWS.DynamoDB.DocumentClient()

exports.handler = (event, context, callback) => {
    const httpMethod = event.httpMethod
    const params = {
        'TableName': 'todoTable'
    }
    dynamo.scan(params, function (err, data) {
        const response = {
            statusCode: 200,
            body: JSON.stringify(data.Items)
        }
        callback(null, response)
    })
};

クライアント側でbodyからtodoListを取り出し表示するようにします。

続いてPOSTメソッド。

const AWS = require('aws-sdk')
const dynamo = new AWS.DynamoDB.DocumentClient()

exports.handler = (event, context, callback) => {
    const params = {
        'TableName': 'todoTable',
        'Item': {
            'id': event.id,
            'todo': event.todo
        }
    }
    dynamo.put(params, function(err, data) {
        if (err) {
            console.log('error')
        } else {
            console.log('success')
            const response = {
                statusCode: 200,
                body: JSON.stringify(data)
            }
            context.done(null, response)
        }
    })
};

try-catchでやるべきですが、今回は簡略化のためこのような実装にしました。(あとで全てtyr-catchに直します)
なぜかここでcallbackを使うと怒られました。
理由分かる方、教えていただきたいです。

あとはAPIGatewayでこれらの関数を各メソッドに割り当てて、デプロイしてください。
詳細は省きます。

クライアントサイド

今回はjQueryは使わずにXMLHttpRequestを使用して実装します。

まずは、画面がロードされた際にGETメソッドでテーブルの項目を取得し、表示をします。

window.onload = () => {
    const request = new XMLHttpRequest()

    request.open('GET', 'https://ほにゃらら.amazonaws.com/dev', true)
    request.responseType = 'json'

    request.onload = event => {
        const data = this.response
        const todoList = JSON.parse(data.body)
        for (task of todoList) {
            const item = task.todo
            // HTMLのulにliを突っ込むだけのメソッド
            createTodoList(item)
        }
    }

    request.send()
}

特に難しい部分はなし。

続いて、TODOを追加した際に走るイベントを追加。

// addというinputタグにイベントを追加
const addTask = document.querySelector('.add')
addTask.addEventListener('submit', e => {
    e.preventDefault()

    const id = Math.random().toString(36).slice(-8);
    const task = addTask.add.value.trim()
    const item = {
        'id': id,
        'todo': task
    }

    const request = new XMLHttpRequest()
    request.open('POST', 'https://ほにゃらら.amazonaws.com/dev/insert', true)
    request.setRequestHeader('Content-Type', 'application/json' );

    request.send(JSON.stringify(item))

    if (task.length){
        createTodoList(task)
        addTask.reset()
    }
})

これで完成です。サーバーレスは短時間で割といろいろできて楽しいですね!

躓いたところ

CORS問題

Access-Control-Allow-Origin 

これを理由にずっと怒られていました。
↓参考記事
【解説付き】chromeでXMLHttpRequestをローカルのファイルで行う方法
AWS API Gateway クロスドメイン通信

XMLHttpRequestのパラメータの渡し方

現在のコード

request.send(JSON.stringify(item))

過去のコード(エラー発生)

request.send(item)

JSON形式にしておらず、30分くらい悩まされていました。。。

終わり

今後はUPDATE、DELETEの実装をし、全て1つの関数にまとめたいと思っています。
それが終わったらなんかしらアプリ作ってみようかな。