🤨

Lambda + API GatewayでHTMLからPOST通信して、内容によって表示を分岐させる

2023/08/02に公開

概要

キーワードを入力できるページAがある。
あるキーワードを入力し、POSTで送信する。
キーワードが正しいものであればページBを表示し、正しいキーワードでなければページCを表示する。

  • ページAへはGETでアクセスする。
  • ページB, CへはPOSTでアクセスする。

使用AWSサービス

  • API Gateway
  • Lambda Python 3.11

参考サイト

AWS LambdaでHTMLを出力してみた
https://qiita.com/yoshidasts/items/d58c555aed2693e99ae6

こちらのサイトを参考に作成しようとしてみたが、かなり前の記事であるためか詳しい設定方法が今と違いよく分からなかったので備忘録として残しておく。

API Gatewayの設定

  • REST API

決め打ちの部分はAPI Gatewayのマッピングテンプレートを使って返す

HTMLを返すには

ポイントは

  • 「統合リクエスト」で統合タイプがいうれであっても「プロキシ統合の使用」のチェックをはずす (プロキシ統合を使用すると「統合レスポンス」の変更ができないため)
  • 「統合レスポンス」で「コンテンツの処理」を「パススルー」から「テキストに変換」に変更
  • また、ここでマッピングテンプレートを設定する
  • 「メソッドレスポンス」の「コンテンツタイプ」がデフォルトでapplication/jsonになっているのでtext/htmlに変更する

おまけ

  • Lambdaから返すHTTPステータスコードによってマッピングテンプレートを変えられた!

構成

今回、API GatewayはLambdaのトリガー側から作成。

Aページ(GET)

入力フォームを設置したページ。
GETの際は特にLambdaでの処理は必要なかった

メソッドリクエスト

特に。そのまま。

統合リクエスト

前述の通り、特に何かの処理が必要なかったため、Mockを選択。
他の設定は特になし。

統合レスポンス

  • メソッドレスポンスのステータスが200の設定が1行あるので、左端の▶をクリック。(絶妙に優しくないUI)
  • コンテンツの処理はパススルーでOK
  • マッピングテンプレートのみ編集する。
  • 「マッピングテンプレートの追加」をクリックし、Content-Typetext/htmlとする。右の小さいチェックマークを押す。(これもまた優しくない(略))
  • テンプレート内にHTMLを入力。

メソッドレスポンス

  • HTTPのステータスが200の1行があるので、左端の▶をクリック。
  • 200のレスポンス本文とあるところの「レスポンスモデルの追加」をクリック。
  • コンテンツタイプにtest/htmlを指定する。

Bページ, Cページ(POST)

Aページから送られてきたキーワードを処理した結果を表示するページ。

メソッドリクエスト

同じく特に。そのまま。

統合リクエスト

こちらはLambdaに入力されたキーワードを処理したいため、統合タイプLambda関数に。
ここで冒頭のポイント通りLambdaプロキシ統合の使用のチェックは外しておくこと。

この時、HTTPからPOSTされた値をそのまま使いたかったが、「JSONで受け取る」との記述の記事が多かったので調べたところ、値の受け取りにマッピングテンプレートを使用すればLambdaにうまく渡せるようだった。

下記の参考記事のように設定

HTMLフォームからAPIGatewayを使ってAWS LambdaにPOSTする
https://qiita.com/satetsu888/items/40fc387735192b794da8

統合レスポンス

  • Aページと同様に開く
  • コンテンツの処理テキストに変換(必要な場合)に変更。
  • ここで画面右の「保存」を押しておくこと。
  • Aページと同様にマッピングテンプレートを設定し、Lambdaから返ってくる値によって「正しい!」(Bページ用)や「正しくありません...」(Cページ用)など分岐させる。
  • Lambdaからのステータスコードによるページの分岐については後述。

メソッドレスポンス

  • ページAと同様に設定

Lambdaからのステータスコードによるページの切り替え

マッピングテンプレート内でif文による分岐をしてもいいが、内容があまりにも違う予定なためLambdaからのレスポンスによって表示内容をまるっと変更できるようにしたい。

こちらの記事を参考に設定

API Gateway + Lambda(Python) の REST API でステータスコード管理をする
https://qiita.com/kuribo2110/items/82b069f51ef499eb2ac6

試してみたところ、Lambdaからの実際のHTTPステータスコードというよりはエラーメッセージの合致でAPI Gateway的になんのステータスコードとして処理をするか、という分岐をしている印象。

まずはメソッドレスポンス

メソッドレスポンスで扱うHTTPステータスコードを増やしてからでないと諸々の設定ができないため、まずはそちらを増やす。
200は使用済みのため、なんかいい感じのステータスコードをチョイス。

  • 「レスポンスの追加」を押してHTTPステータスコードを入力
    これだけ。

統合レスポンス

  • 「統合レスポンスの追加」を押す。
  • Lambdaエラーの正規表現に選択したステータスコードを入力
  • メソッドレスポンスのステータスでメソッドレスポンスにて追加したステータスコードを選択
  • コンテンツの処理テキストに変換(必要な場合)に変更
  • マッピングテンプレートにこれまでと同様に設定をする

Lambda側の処理

Lamdbaでは前述の新しく作成したレスポンスに遷移させたい処理の箇所に

# XXXは自分で設定したステータスコード
raise Exception('XXX')

とすれば統合レスポンスで設定したLambdaエラーの正規表現に合致し、それぞれのテンプレートの内容を表示することができる。

終わりに

以前は日本語訳されていなかったためにどこの部分の設定が必要なのかがすぐに分からず、さらにいろんなところに「マッピングテンプレート」という言葉が出てきてこれもHTMLを出力するのにどこをいじればいいのかが分からなかった。

今回の知見でようやく何に作用する「マッピングテンプレート」なのかが分かったのでヨシ!

Discussion