AWS Lambdaで動的コンテンツ配信を考えてみる

いつも忘れないように、コンセプトから。

###コンセプト
・お金かけてまでやりたくないのでほぼ無料でAWSを勉強する
　→ちょっとしたサービスを起動すると結構高額になりやすい。
・高いレベルのセキュリティ確保を目指す
　→アカウントを不正に使われるととんでもない額を請求されるので防ぐ

[先日やってみたチュートリアル](https://qiita.com/auf/items/74578049ef2f668f9d60)をもう少しシンプルに勉強してみようと思います。LambdaとAPIGatewayだけで、HTMLを生成するのが目標です。

いくつかサイトを見てみましたが、
https://triobog.hateblo.jp/entry/2018/09/23/234739
こちらで行っているのを真似します。そのまんまなんで、記載するほどでもないんですが、自分の備忘とちょっとはまったところをがあったので記載してみます。

###とりあえずやってみる

まずはLambdaを作成します。デフォルトで作っただけなので、ここは後で書き換えます。
![TestLambda1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480659/b05abb4f-fb26-9d8f-c1ab-8d2e5c3c71f3.png)

念のため生成したLambdaをテストしてみます。うまくいっているようです。
![TestLambda2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480659/d82e9b90-f254-c7fc-43ee-b207beec2afe.png)

続いてAPIGatewayを作成します。API名は適当です。この辺はリンク先とは画面が変わっていました。Websocketが使えるようになったからかな。RESTのボタンを押してもプロトコルを選択すると出てくるあたりは「なんで？」って感じでしたけど。
![TestLambda3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480659/d3f76d8b-36f8-a603-073e-97110e77123f.png)

アクションでメソッドを作成していきます。今回は動的に生成と言ってもHTMLを返すだけなのでGetで作成します。
![TestLambda4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480659/2f792242-9bae-4d2a-9fee-f4e4eee84393.png)

Getのセットアップをしていきます。
![TestLambda5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480659/32a0531d-d799-e79a-9efd-48571380dec3.png)

前回と同じチュートリアルの画面までやってきました。クライアントからの矢印の順にセットアップしていきます。
![TestLambda6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480659/e430fe8b-9df7-d9ce-192a-5939b3803b7c.png)

URLのパラメーターを設定します。URLの最後にinputMsgで値を設定すると、次に引き渡すことができます。
![TestLambda7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480659/8a148e3a-9e96-01c0-3277-f995a1d20223.png)

次に統合リクエストの設定です。受け取ったリクエストをバック側のLambdaに引き継ぐための設定です。今回はinputMsgで引数を受け取っているので、Content-Typeに「application/json」を設定して引き渡します。
![TestLambda8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480659/07dc19df-9129-b2db-7530-7fdc1c9dd9cd.png)

続いてLambdaのコードを書き換えます。inputMsgで受け取った値をそのまま返すだけです。
![TestLambda9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480659/3afa5d72-05d7-8983-9fd0-6fd4ce0718ac.png)

今度は統合レスポンスの設定です。Lambdaからの戻り値を設定します。
![TestLambda10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480659/4250c91b-d8a6-e6be-3fb0-002aa462d01d.png)

統合レスポンスのマッピングテンプレートを開いて、受け取った値をHTMLに埋め込みます。
![TestLambda11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480659/dd530244-d87e-7459-7100-23393b6a9ca3.png)

右側のようにHTMLを記載しておきます。
![TestLambda12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480659/13dfdbb5-8abe-1839-7052-f8e87440aa35.png)

で、アクションからデプロイします。
![TestLambda13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480659/fbfccb70-ec86-03ef-73bd-aa0e68e68120.png)

APIのデプロイでステージ名を適当に設定します。
![TestLambda14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480659/923e0c19-8c59-8e91-3859-3eb883796a47.png)

デプロイできたのでURLを叩いてみると、テキストのまま表示されています。HTMLはうまく帰ってきているので、問題は最後のレスポンスですね。。。
![TestLambda15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480659/b9083d16-9e61-4839-1475-e3e22b993d92.png)

レスポンスの設定でtext/htmlに変更します。ここの設定でブラウザ側が認識してくれます。
![TestLambda16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480659/3f62043a-7d96-7d6e-31ad-33d35e62b9a2.png)

て、ことで再度アクセスしてみます。無事に取得できました。
![TestLambda17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480659/116e274f-1fa3-46f0-a407-033e063bd8d4.png)

###少し頭を整理してみる

うまくいったものの、このままでいいかは少し考えてみる必要がありそうです。サーバー側（と言ってもサーバーレス）の処理はLambdaで実行できています。前回のチュートリアルと同じようにLambdaにデータベースへのアクセス権限を与えて実装すればいろいろなことはできるでしょう。ただ、問題もいろいろありそうです。ざっと思いつく問題は以下です。

- HTMLの生成ってこれでいいのか？簡単な記載ならこれでも良さそうだけど、複雑な生成をしようとすると統合レスポンスの記載は不便そう
- Lambdaの処理でDBアクセスする場合のセキュリティ設定はどうすべきかがまだわかっていません。直接Lambdaにどうこうすることはできないので、APIGatewayの設定をミスしていなければ問題ないのかもしれませんが（APIGatewayをDMZ的な働きにできる？）もうちょっと検討は必要
- URLからの値を引き渡してDBへのクエリに使う場合はSQLインジェクション対策が必要（普通のアプリと同じ）

一番の問題は1つ目の課題かなぁと思います。事前にいくつかのサイトを調べたんですが、
https://qiita.com/hkusu/items/13af2b1a328719ea2946
だとLambdaでHTMLを生成しています。それでもできなくはないですが、問題は何も解決していないので、もうちょっと考察が必要ですね。一旦今日はここまで。