API Gateway Lambdaプロキシ統合を有効にしてエイリアスごとに通信する方法

## はじめに
Lambdaプロキシ統合が以下の資料だとオフの状態の資料しかないので、Lambdaプロキシ統合をオンにした状態でもうまくいくのかについて確認します。
> c. [Lambda プロキシ統合] はオフのままにしておきます。
https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/amazon-api-gateway-using-stage-variables.html


## アーキテクチャ



今回のシナリオとして、あるAPIを公開中であり、Version2のbeta版の検証も実施するという想定になります。
バージョンについては、
- v1というAPIバージョンを現行版として公開中。
- v2betaを現在開発中でプレリリース版として公開中。

というシナリオで開発をすすめるという想定とします。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/872532/e769e979-f700-5bf1-0a7c-f7cce421b01a.png)

## セットアップ


### API Gateway

#### リソース
以下のように、① **Lambda プロキシ統合をTrue** に設定し、② Lambda関数を`関数名:${stageVariables.ステージ変数}`に設定する必要があります。
上記の`ステージ変数`部分は各ステージの「ステージ変数」で定義します。(詳細は後ほど。)
今回は`Alias`というステージ変数を定義しますので`${stageVariables.Alias}`となります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/872532/ca2dd726-c53e-34de-bfb0-f1bed77313d5.png)

#### ステージ
ステージをv1、v2betaといったバージョンごとに作成します。
ステージ変数を`Alias`として、各ステージごとにバージョンの値を入力します。
v1の結果は以下の通りとなりますのでv2betaも同様の手順で作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/872532/7fddec33-5c5b-176f-7c88-d3385dc5a25c.png)

ステージ変数による具体的な設定内容は以下の通り。
https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/aws-api-gateway-stage-variables-reference.html

#### カスタムドメイン名
設定する必要はないですが、カスタムドメイン名もついでに設定。
URIは以下のように`https://example.com/<バージョン>/<リソース名>`とします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/872532/31b83408-5e3b-d598-815c-dd2a17d4a50e.png)


### Lambda
#### エイリアス
エイリアス名はAPI Gatewayのステージ変数で定義した値と同じエイリアス名を作成することで以下のがぞうのようになります。

v1は明示的にバージョンを指定し、v2betaは$Latestを定義します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/872532/926349eb-e440-a2fc-4e0b-50e385566878.png)

#### バージョン
バージョンは以下の通り。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/872532/948a80d5-3e46-9738-7b98-adca64d38c35.png)

以下はバージョンごとのLambdaになります。
v1のコードでは「prd」と出力されるだけの結果になります。
```python:lambda_function.py
# version 1
import json

import logging

logger = logging.getLogger()
logger.setLevel("INFO")

def lambda_handler(event, context):

    return {
        'statusCode': 200,
        'body': json.dumps('prd')
    }
```

v2のコードでは「latest」と出力されるだけの結果になります。
```python:lambda_function.py
# version 1
import json

import logging

logger = logging.getLogger()
logger.setLevel("INFO")

def lambda_handler(event, context):

    return {
        'statusCode': 200,
        'body': json.dumps('latest')
    }
```

#### パーミッション

API Gatewayのコンソール上で、[API名 > リソース > 統合リクエストを編集]上で関数を入力すると、Lambdaパーミッションを追加する以下のようなコマンドが出力されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/872532/4bbebce7-ff50-a4fc-ff51-b153087835ea.png)

上記のコマンドをLambdaのエイリアス分だけ実行します。今回はv1, v2betaとLambdaエイリアスを作成したので以下のコマンドをそれぞれ実行します。
```bash
# v1
aws lambda add-permission \
--function-name "arn:aws:lambda:＜リージョン＞:＜アカウントID＞:function:＜関数名＞:v1" \
--source-arn "arn:aws:execute-api:＜リージョン＞:＜アカウントID＞:＜API ID＞/*/GET/demo_momento" \
--principal apigateway.amazonaws.com \
--statement-id ＜任意の文字列＞ \
--action lambda:InvokeFunction

# v2beta

aws lambda add-permission \
--function-name "arn:aws:lambda:＜リージョン＞:＜アカウントID＞:function:＜関数名＞:v2beta" \
--source-arn "arn:aws:execute-api:＜リージョン＞:＜アカウントID＞:＜API ID＞/*/GET/demo_momento" \
--principal apigateway.amazonaws.com \
--statement-id ＜任意の文字列＞ \
--action lambda:InvokeFunction
```

上記のコマンドを実行し、Lambdaコンソールから [エイリアス > トリガー]と遷移することでトリガーが作成されていることが確認できます。
設定すると何故かエラーが発生していますが問題なく接続はできます。エラーはありますがひとまず無視で次に進みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/872532/c738c3e9-1b60-256f-2126-27eaad3441be.png)


** テスト
v1の結果は以下のようになります。
Lambdaもv1エイリアスの値が反映されていることがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/872532/65f1dd91-37df-6f17-37e4-088a9580eb36.png)


v2betaの結果は以下のようになります。
v2betaのエイリアスの値が反映されていることがわかります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/872532/4f6afaf6-ac39-6da4-cbe1-993d6cb8371a.png)

各エイリアスごとにAPIコールをすることは成功です。

## 終わりに
以上のようにLambda プロキシ統合を有効にしている場合でも、各エイリアスごとにAPIコールすることができました。

とはいえ、エラーの画面が出ているのはこれは如何に、、
(ステージ変数として機能していない？)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/872532/c738c3e9-1b60-256f-2126-27eaad3441be.png)