プレスリリースやお知らせ、開発ブログ、会社の活動状況、Mattermost・aws・AI等の技術情報などを発信しています。

TallyのデータをAWS Lambda Function URLsに投げつけてみる

こんにちは sakasai です。

カフェはタリーズ派です。

今年の4月頃にAWS Lambda Function URLsが発表されました。

https://aws.amazon.com/jp/blogs/news/announcing-aws-lambda-function-urls-built-in-https-endpoints-for-single-function-microservices/

AWS Lambda Function URLsとは

AWS Lambdaで手軽にエンドポイントURLを追加できる機能です。

これまではAPIとしてAWS Lambdaを動作させるには、API GatewayやAppSyncのバックエンドなどに設定する必要がありましたが、Function URLsによってLambda単体でかんたんにAPIとして使うことができるようになりました。

以前、Tallyのご紹介で下記ブログを投稿したのですが、TallyのデータをAWS Lambdaに送れたらいろいろできて最高なのではと思い、AWS Lambda Function URLsを使えば簡単にできそうということで今回やってみました。

https://www.d-make.co.jp/blog/2022/04/13/form-on-tally/

Tallyはフォームデータの連携先として、メールやSlack、Google Sheets、Notionなどその他にも多数のサービスと統合することができるのですが、その中のWebhooksを使ってAWS Lambda Function URLsにデータを送ってみます。

はじめに、AWS Lambdaで関数を作成します。

「関数の作成」から

適当な名前を入力し、好きなランタイムを選んで、

「詳細設定」を展開し、「関数URLを有効化」にチェックをします。

認証タイプに「AWS_IAM」と「NONE」が選択できますが、今回は「NONE」にしました。

画面上の説明書きにもありますが、認証タイプをNONEにした場合、パブリックなエンドポイントになりますので、セキュリティ等十分注意してご使用ください。

その他はデフォルト(チェックなし)のまま「関数の作成」を押下します。

関数の作成が完了すると関数URLが確認できます。

URLにアクセスすると、"Hello from Lambda!"が返ってきます。

一旦関数の中身を以下のようにしてeventの中身を確認できるようにしておきます。

次にTallyでフォームを作成します。

「Create form」で今回は以下のフォームを作ってみます。

プレビューすると以下のようになります。

フォームを公開したらフォーム設定のIntegrationsで「Webhooks」を選びます。

Endpoint URLにAWS Lambdaの関数URLを入力します。

設定できると以下のように表示されます。

それではフォームの送信を行ってみます。

以下の内容で送信

Tally上のSummaryを見ると送信データが確認できます。

AWS Lambdaのログを見るとeventの中身は以下のようになっています。

{
  'version': '2.0', 
  'routeKey': '$default', 
  'rawPath': '/', 
  'rawQueryString': '', 
  'headers': {
    'content-length': '2266', 
    'x-amzn-tls-cipher-suite': 'ECDHE-RSA-AES128-GCM-SHA256', 
    'x-amzn-tls-version': 'TLSv1.2', 
    'x-amzn-trace-id': 'Root=1-xxxxx-0000000000', 
    'x-forwarded-proto': 'https', 
    'sentry-trace': 'xxxxxxxxxx', 
    'host': 'xxxxxxxxxx.lambda-url.ap-northeast-1.on.aws', 
    'x-forwarded-port': '443', 
    'content-type': 'application/json', 
    'x-forwarded-for': '99.99.99.99', 
    'accept': 'application/json, text/plain, */*', 
    'user-agent': 'axios/0.26.0'
  }, 
  'requestContext': {
    'accountId': 'anonymous', 
    'apiId': 'xxxxxxxxxx', 
    'domainName': 'xxxxxxxxxx.lambda-url.ap-northeast-1.on.aws', 
    'domainPrefix': 'xxxxxxxxxx', 
    'http': {
      'method': 'POST', 
      'path': '/', 
      'protocol': 'HTTP/1.1', 
      'sourceIp': '99.99.99.99', 
      'userAgent': 'axios/0.26.0'
    }, 
    'requestId': 'xxxxx-xxxx-xxxx-xxxx-xxxxx', 
    'routeKey': '$default', 
    'stage': '$default', 
    'time': '28/Jun/2022:12:44:33 +0000', 
    'timeEpoch': 1656420273862
  }, 
  'body': '{
    "eventId":"xxxxx-xxxx-xxxx-xxxx-xxxxx",
    "eventType":"FORM_RESPONSE",
    "createdAt":"2022-06-28T12:44:32.975Z",
    "data":{
      "responseId":"xxxxx",
      "submissionId":"xxxxx",
      "respondentId":"zzzzz",
      "formId":"zzzzz",
      "formName":"テストフォーム",
      "createdAt":"2022-06-28T12:44:32.000Z",
      "fields":[
        // フォームデータ(後述)
      ]
    }
  }', 
  'isBase64Encoded': False
}

フォームデータ(フォームに関連する情報)はbodyの中にjson文字列として入っているようです。

formIdはフォームの公開URLの末尾の文字列が入っています。

formNameはフォームのタイトルそのままですね。

Lambda関数を以下のように変更してもう一度フォーム送信してみます。

fieldsにフォームの項目ごとのデータが配列で入っています。

ログに出力された内容を項目ごとに見てみようと思います。

テキストボックス

{
    "key":"question_12345",
    "label":"テキスト",
    "type":"INPUT_TEXT",
    "value":"テキスト"
},

テキストエリア

{
    "key":"question_23456",
    "label":"テキストエリア",
    "type":"TEXTAREA",
    "value":"テキスト\\nエリア"
},

ラジオボタン

{
    "key":"question_34567",
    "label":"ラジオ",
    "type":"MULTIPLE_CHOICE",
    "value":"34b1f9d5-cdc7-4079-868d-57818e0b196b",
    "options":[
        {"id":"34b1f9d5-cdc7-4079-868d-57818e0b196b","text":"ラジオ1"},
        {"id":"86afe98b-3f9c-44e5-98f0-54bf3f325614","text":"ラジオ2"},
        {"id":"851f2209-78e7-46f1-a238-9c28ed86296c","text":"ラジオ3"}
    ]
},

チェックボックス

{
    "key":"question_45678",
    "label":"チェックボックス",
    "type":"CHECKBOXES",
    "value":[
        "40d02795-8037-499d-a143-b5c9c9dc1661",
        "25f11dd5-dd45-42fe-8461-64f336f99045"
    ],
    "options":[
        {"id":"40d02795-8037-499d-a143-b5c9c9dc1661","text":"チェック1"},
        {"id":"25f11dd5-dd45-42fe-8461-64f336f99045","text":"チェック2"},
        {"id":"a900550c-6ced-485c-a731-19f85611ff3a","text":"チェック3"}
    ]
},
{
    "key":"question_45678_40d02795-8037-499d-a143-b5c9c9dc1661",
    "label":"チェックボックス (チェック1)",
    "type":"CHECKBOXES",
    "value":true
},
{
    "key":"question_45678_25f11dd5-dd45-42fe-8461-64f336f99045",
    "label":"チェックボックス (チェック2)",
    "type":"CHECKBOXES",
    "value":true
},
{
    "key":"question_45678_a900550c-6ced-485c-a731-19f85611ff3a",
    "label":"チェックボックス (チェック3)",
    "type":"CHECKBOXES",
    "value":false
},

プルダウン

{
    "key":"question_56789",
    "label":"プルダウン",
    "type":"DROPDOWN",
    "value":"1735d5db-6ad9-40b1-82ef-36864b47eb8a",
    "options":[
        {"id":"43c27feb-0645-414a-8194-8b95fc6ec75b","text":"プルダウン1"},
        {"id":"9995e383-0d66-44c5-b3dd-b35401d39a18","text":"プルダウン2"},
        {"id":"1735d5db-6ad9-40b1-82ef-36864b47eb8a","text":"プルダウン3"}
    ]
},

ファイル

{
    "key":"question_67890",
    "label":"ファイル",
    "type":"FILE_UPLOAD",
    "value":[
        {
            "id":"w8xPBz",
            "name":"test.txt",
            "url":"https://xxxxxxxxxx.com/tally-response-assets/xxxxx/test.txt",
            "mimeType":"text/plain",
            "size":12
        }
    ]
}

テキストボックス、テキストエリアは値がそのまま入ってますね。テキストエリア内の改行もちゃんと送られてくるようです。

ラジオボタン、プルダウンはoptionsに選択項目のリストが入り、valueに選択値のidが入っているようです。

チェックボックスはラジオボタンと同様なものに加えてそれぞれの選択値も項目として渡されるようです。単一選択と複数選択の違いでしょうか。

ファイルはvalueにファイルのデータそのものではなく、Tallyにアップロードされているファイルの情報(クラウドストレージのURL等)がわたされる形のようです。

以上、TallyのフォームデータをAWS Lambda Function URLsに送信してどのように取得できるかを確認しました。

今回はログ上でデータを確認するまでしかやってませんが、DynamoDBに登録したりなどLambdaにデータを送ることでいろいろできそうです。

セキュリテイに関しても関数内でformIdやformNameでチェックするなどで不正なアクセスなどを省くこともできるかなと思います。

TallyとAWS Lambda Function URLsはとても便利なので色々活用できたらいいなと思います。

  • B!

おすすめ記事リンク