AWS Lambda + API Gatewayで動的ページを動かす

# はじめに
AWS LambdaとAWS API Gatewayを使用して、
サーバレスなお天気アプリを作成したので内容をまとめました。


# 目次
* 基本的なHTTPの動き
* HTTPの中身
* API Gateway
* AWS Lambda
* Layerについて
* [図解]API Gateway + Lambda統合
* 完成

# 基本的なHTTPの動き
まず、Webアプリをサーバレス化する際に必要な知識としてHTTPの動きを理解しておくとスムーズに出来ます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1194812/c17491a2-a532-8693-d2e9-772eab4744ea.png)
引用：[第1回HTTPプロトコルとは](https://www.atmarkit.co.jp/ait/articles/1703/29/news045.html)より

HTTPバージョンは、HTTP/1.1, HTTP/2., HTTP/3とありますが、今回は、HTTP/1.1で説明していきます。

**1. 【クライアント】URLにアクセス。画像なども同時に数個までリクエスト可能**
**2.  【Webサーバー】該当するページ情報を探し出してクライアントに返却**
**3.  【Webサーバー】画像などの要求があればリクエスト順に返却**

HTTP/2の場合、リクエスト数を同時に数十個まで可能。同時にレスポンスを返します。
HTTP/2を使用する場合は、暗号化が必須になっています。(URLの暗号化についてはこの後、説明。)


# HTTPの中身
HTTPがどのような情報を受け取り、返却しているのかを確認するには、ブラウザの検証ツールを使用します。

* **検証ツールを開き、「Network」を選択します。**
* **「Network」タブを開き閲覧したい情報のNameをクリック**
* **コンソール画面右側に、情報が表示**
    * General(リクエスト行)
    2. レスポンスヘッダー
    3. リクエストヘッダー の順番に表示されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1194812/3f05837e-ba8b-1de1-4b9f-43445f3e24d0.png)
**主にLambda実装時に必要な情報は以下になります。**
Request Method：GET
Content-Type：受け入れ可能な形式
StatusCode：200
body：htmlのコード情報など



# API Gateway
AWSサービスの API Gatewayについて説明していきます。

### 概要
* クライアントから受け取ったリクエストを、サービスにルーティング。
* 実際にクライアントが叩くのは、API Gatewayの API部分のみ。
* バックエンドポイント(Lambda)とMethodを統合。
* どこに立てるかによってプロトコルバージョンが異なる
    * global：HTTP/2
    * VPCエンドポイント：HTTP/1.1
    * Cloud Formationでバージョンを選択することも可能

### REST API
今回は、Lambda関数の中で条件分岐を行いたいので、REST APIを使用しました。

* メソッドリソースを１つ以上持つことが可能。
* 受信リクエストを、Lambda統合エンドポイントに転送。

# AWS Lambda
AWSサービスのLambdaについて説明していきます。

### 概要
* FaaSなサービス
    * 任意なプログラムが実装可能
    * 処理内容は開発者が実装
* サーバーレス:運用保守も不要
    * 今までは、サーバー + ミドルウェアも運用管理
* Lambda関数を呼び出したクライアントに返す。
* 呼び出しリクエストに対するHTTPレスポンスはJSONにシリアル化される。
* アクセス数に応じたプログラムが起動するので、負荷分散を自動で可能。
* EC2での負荷分散に必要なAuto Scalingも不要


# LambdaのLayer
Layerとは、Lambda のモジュールや共通処理を Layer にして複数のLambda関数からコールすることができる機能です。

### 外部ライブラリを使用する時
Layerを追加しないと外部ライブラリを使用することが出来ないため、
毎度ローカルでzipファイルを作成してアップロードしなくてはいけない。

そこで、便利なのが、Pythonのモジュールをパッケージ化して
ARNの値をLayerに指定するとすぐに使用できるGithubがあります。
[keithrozario/Klayers: Python Packages as AWS Lambda Layers](https://github.com/keithrozario/Klayers)



# API Gateway + Lambda統合
API GatewayとLambdaを統合することによって、どんなことが可能になるかを説明していきます。

* 今回、作成したお天気アプリが、index.htmlと座標情報を取得するgeo.jsで座標情報を取得。
* 座標情報を元に[OpenweatherMap API](https://openweathermap.org/api)を叩いて、weather.htmlで天気情報を返す。というアプリを制作。
* クライアントが、リクエストをすると、APIを叩いて、Lambdaにあるファイルを探してリクエストPathとメソッドで指定したファイルを探す。



### 概要
* 統合されたLambda関数にリクエストやパスの情報(*1)が回ってくるのでAPIの設定でLambda統合を使用。
* リクエストパラメータの順序は保持されない。
* API Gatewayでの設定により統合リクエスト及び統合レスポンスが自動で設定される。

(*1) rawリクエスト = リクエスト全体を印刷

## [図解]
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1194812/595a2b7b-be89-badc-60f5-c7d126ccd1c0.png)

###　Lambda関数に条件分岐を追加して、pathにあったテキストファイルを返却したい時。
* ランタイム：Python3.8
    * 下記のような形式に沿って、returnを記述していきます。
    * Lambda関数のディレクトリ構成に、templateファイルを埋め込み、pathと
    * 条件に記述したpathとmethodに沿ったテンプレートファイルを返却するように、Content-Typeや、bodyを適宜変更してください。

````Python
return {
            "statusCode": 200,
            "headers": { "Content-Type": "text/html"},
            "body": template.render(hoge),
            "isBase64Encoded": False
        }
```


# 最後に
私は、Lambdaでは何をしていて、何ができるのか。ということがわからずに実装を進めていました。
HTTPの中身とLambdaやAPI Gatewayで何を行っているのかということを理解することで、
その後はスムーズに一からで実装出来ました。

あまり、このようなWebアプリをLambda + APIGatewayで実装する場面はないかとは思いますが、、、。
どなたかの参考になれば幸いです。
以上、ありがとうございました。