はじめに
こんにちは。あつしです。
Googleフォームで入力されたデータを、AWSのDynamoDBに登録するアプリを作ってみたいと思います。
以下のようなことをお考えの人たちに参考になれば幸いです。
- GoogleフォームからPOSTでAWS(API Gateway)にデータをPUTする
- API GatewayとLambdaの連携方法
- API GatewayとLambdaにJSONを渡して単体テストする方法
この検証が終わったあと、あることに気づきました。Googleフォームの場合、API GatewayのCORSを有効にする必要がありませんでした。
全体像
使用するリソース
使用するリソースは以下となります。
- Googleフォーム
- Google Apps Script
- API Gateway
- Lambda
- DynamoDB
構成図
つながりを表して図にすると以下のようになります。
やってみる
DynamoDB
一番うしろのDynamoDBから作っていきます。
AWSコンソールにログインしてDynamoDBコンソールに移動します。「テーブル」から「テーブルの作成」をクリックします。
テーブル名は”inquiry-table”としました。パーティションキーは必須なので、文字列型で”email”としました。
他はデフォルト設定で、「テーブルの作成」をクリックしました。
Lambda
つぎはLambdaを作っていきます。API Gatewayから受け取ったデータをDynamoDBに投入する役割です。
関数名は”putDynamoFunc”としました。Python 3.9を使用することとして、一から作成しました。
コードは下記になります。event変数にAPI Gateway(Google Apps Script)から受け取ったJSONデータが入っています。これらを取り出して、DynamoDBにPUTしています。
import json
import boto3
def lambda_handler(event, context):
# API Gateway(GAS)から受け取ったデータを取り出して変数に格納
Email = event['email']
Name = event['name']
Gender = event['gender']
Inquiry = event['inquiry']
# DynamoDBに投入するためのアイテムをセット。JSONを作成して変数に格納
DynamoItems = {
'email': Email,
'name': Name,
'gender': Gender,
'inquiry': Inquiry
}
# DynamoDBにデータを投入
table = boto3.resource('dynamodb').Table('inquiry-table')
response = table.put_item(
Item = DynamoItems
)
return {
'statusCode': 200,
'body': json.dumps(response)
}
LambdaがDynamoDBにデータを投入することができるように、権限を加える必要があります。Lambdaに付与されているロールを編集するので、「設定」→「アクセス権限」→「実行ロール」欄にあるロール名をクリックします。
IAMコンソールに飛ぶので、アタッチされているポリシーをクリックします。
「ポリシーの編集」をクリックします。
JSON形式で編集しました。今回はすべてのDynamoDBリソースへすべてのアクションを許可しました。追加した箇所は赤枠で囲っています。
追加したJSONコードだけ抜粋したのが下記です。
{
"Effect": "Allow",
"Action": "dynamodb:*",
"Resource": "*"
}
確認画面が出ます。DynamoDBへのフルアクセスがついていますね。「変更の保存」をクリックします。
Lambdaを単体でテストしてみます。後述しますが、API Gateway(Google Apps Script)から以下のようなJSON形式のデータがLambdaに渡されます。
エラーが出ないことを確認します。
DynamoDBのテーブルを見てみます。レコードが入っています。
API Gateway
Googleフォームに入力されたデータを受け取る役割です。また、受け取ったデータをLambdaに渡します。
REST APIで構築します。
名前は”api-GAStoLambda”としました。
リソースの作成を行います。アクセスするURLの一部となるところです。
リソース名は”test”としました。最終的にアクセスするURLの末尾が「…/test」となります。
メソッドの作成をしていきます。
今回はGoogleフォームからPOSTでで受け取るのでPOSTメソッドを作成します。
統合タイプには「Lambda関数」を選び、先ほど作ったLambda関数の名前(ここでは”putDynamoFunc”)を入力し、「保存」ボタンをクリックします。
API GatewayにLambda関数を呼び出す権限を付与する、というメッセージが表示されるので、「OK」をクリックします。
API Gatewayの単体テストをしてみます。「テスト」をクリックします。(下図参照)
リクエスト本文に先ほどと同じようなJSONを記入して(今回は変数の先頭に”API”をつけました) 、「テスト」をクリックします。
ログでエラーが発生していないことを確認します。
DynamoDBを見てみると、新しいレコードが追加されています。
デプロイしないと外部からアクセスできないので、デプロイします。
新しいステージである”v1″を作って、そこにデプロイしました。
デプロイするとAPI Gatewayの呼び出しURLが表示されます。これは後述するGoogle Apps Scriptに埋め込むものなので、メモしておきます。
Googleフォーム
Googleフォームを作ります。
ご存知と思いますが、Googleドライブの「新規」ボタンから、「Googleフォーム」をクリックしてGoogleフォームを作成できます。
完成図は以下のようになります。
それぞれ見ていこうと思います。
メールアドレス
Googleフォーム編集画面の「設定」から、「メールアドレスを収集する」にチェックを入れると、メールアドレスを入力する箇所を作れます。
名前
名前は「記述式」となります。
性別
性別は「ラジオボタン」の選択式です。
質問を入力してください
こちらは「段落」となります。
Google Apps Script
GoogleフォームからGoogle Apps Scriptを作成していきます。
Googleフォームの作成画面右上の「…」から、「スクリプトエディタ」をクリックします。
先にコードを記載します。コードの中の変数(api_endpoint)に先ほど確認した、API Gatewayの呼び出しURLを記載します。
function myFunction(event) {
// Emailを変数に格納
var resEmail = event.response.getRespondentEmail();
// フォームに入力されたデータのかたまり(名前、性別、質問)を変数に格納
var resItems = event.response.getItemResponses();
// かたまりからそれぞれの値(名前、性別、質問)を取得して変数に格納
var resName = resItems[0].getResponse();
var resGender = resItems[1].getResponse();
var resInquiry = resItems[2].getResponse();
// JSONオブジェクトを用意する。この中でフォームから受け取ったデータ(Email、名前、性別、質問)をセットする
var jsonObj = {
"email": resEmail,
"name": resName,
"gender": resGender,
"inquiry": resInquiry
}
//
var api_parameters = {
'method': 'post',
'contentType': 'application/json',
'payload': JSON.stringify(jsonObj)
};
// JSON.stringifyでJSON形式の文字列に変換する
//var json = JSON.stringify(obj)
//console.log(json)
var api_endpoint = 'https://mag7j9olvf.execute-api.ap-northeast-1.amazonaws.com/v1/test';
var response = UrlFetchApp.fetch(api_endpoint, api_parameters);
console.log(response);
}
スクリプトエディタの「実行」ボタンを押すと、初回だけ「承認が必要です」というダイアログボックスが表示されます。「権限を承認」をクリックします。
承認するアカウントの選択画面が出るので、クリックします。
「詳細」ボタンをクリックして、「<プロジェクト名>(安全ではないページ)に移動」をクリックします。
スクリプトエディタのプロジェクト(ここでは”フォームプロジェクト”とした)がGoogleアカウントへのアクセスを求めます。「許可」をクリックします。外部サービスとはAPI Gateway(AWS)のことです。
Google Apps Scriptが実行されますが、この段階ではエラーになります。エラーの内容は、「responseが定義されていない」というもの。スクリプトを単体で動かしているため、eventには何も入っていません。そのため、「responseが定義されていない」となっています。
Googleフォームから入力が行わると、Google Apps Scriptが実行されるようにトリガーを設定します。スクリプトエディタの左のトリガーボタンから、「トリガーを作成」ボタンをクリックし、下記のように設定します。
- 実行する関数を選択:Google Apps Scriptの関数名を入力
- 実行するデプロイを選択:Head
- イベントのソースを選択:フォームから
- イベントの種類を選択:フォーム送信時
今度はGoogleフォームがアカウントへアクセスする許可を求められます。初回だけです。
先ほどと同じように「<プロジェクト名>(安全ではないページ)に移動」をクリックします。
Googleフォームからデータを送信してみます。
Google Apps Scriptのログを確認します。エラーは出ずにステータスが「完了」となっていることを確認します。種類はGoogleフォームからトリガーされたので、「トリガー」となっています。
DynamoDBを見てみます。先ほどGoogleフォームから送ったデータが登録されています。
最後に
最後までお読みいただきありがとうございました。
今回の検証をやってみて、いろいろなことが勉強になりました。
- GoogleフォームからGoogle Apps Scriptへ値が渡されて、どのようにGoogle Apps Scriptから取り出すのか。
- Google Apps ScriptからどのようにAPI Gatewayを呼び出すのか。
- API Gatewayでの単体テストの方法
- API GatewayからどのようにLambdaを呼び出すのか。
- JSONデータを受け取ってLambda上での扱い方
- Lamdbaの単体テストの方法
- LambdaからDynamoDBへのPUT方法(これは以外にも簡単だった)
少しでも参考になれば幸いです。
参考にさせていただいたサイトを下記に示します。大変助かりました。ありがとうございました。
参考サイト
【GAS GoogleAppsScript | 基礎コード】JSONデータを扱うためのJSONオブジェクト
【コピペでOK!】GASでGoogleフォーム回答者のメールアドレスを取得する方法
コメント