AWS CDK (Python) を使ってAPI Gateway + LambdaでPOSTを受け取る

AWS CDKとは大雑把に言うと、AWS上で構築するアプリケーションの設計書（CloudFormation）をプログラミング言語で書いてしまおうというもの。
本記事では、POSTされたJSONをAPI Gatewayを通してLambdaで処理するという単純な流れをPythonを用いて実装します。
AWS CDKを使えるようにするための設定は、以下の公式ドキュメント等を参照のこと：

- [Getting started with the AWS CDK](https://docs.aws.amazon.com/cdk/latest/guide/getting_started.html)
- [AWS CDK Workshop](https://cdkworkshop.com/15-prerequisites.html) 

手順
-
まず適当なディレクトリを作り、以下の`cdk.json`を作成します。

```cdk.json
{
  "app": "python3 app.py"
}
```

次にそのディレクトリ内に新しいディレクトリ（例えば`lambda`）を作り、その中にLambdaの関数を作ります（ここでは`webhook.py`）。単純に、リクエストボディ部のJSONをそのまま返すだけの関数です。

```lambda/webhook.py
import json

def handler(event, content):
    try:
        body = event.get("body")
        print(body)
        status_code = 200
    except Exception as e:
        status_code = 500
        body = {"description": str(e)}
    return {
        "statusCode": status_code,
        "headers": {
            "Content-Type": "text/plain"
        },
        "body": json.dumps(body)
    }
```


最後に元のディレクトリに戻り、本丸のアプリを定義していきます（`app.py`）。

```app.py
import os
from aws_cdk import (
    core,
    aws_lambda as _lambda,
    aws_apigateway as apigw
)

class PrintPostStack(core.Stack):

    def __init__(self, scope: core.App, name: str, **kwargs) -> None:
        super().__init__(scope, name, **kwargs)

        lambda_func = _lambda.Function(
            self, "PrintPostFunc",
            code=_lambda.Code.from_asset("lambda"),
            handler="webhook.handler",
            runtime=_lambda.Runtime.PYTHON_3_7,
        )

        api = apigw.RestApi(self, "PrintPostApi")
        api.root.add_method("POST", apigw.LambdaIntegration(lambda_func))

app = core.App()

PrintPostStack(
    app, "PrintPostStack",
    env={
        "region": os.environ["CDK_DEFAULT_REGION"],
        "account": os.environ["CDK_DEFAULT_ACCOUNT"]
    }
)
app.synth()
```

- Stackとは構築されるAWSのリソース全体の集合のことを指す用語です。
- `lambda_func`でLambda関数を設定しています。
    - `code=_lambda.Code.from_asset("lambda")`はLambda関数ファイルが`lambda`ディレクトリにあるよということ
    - `handler="webhook.handler"`は`webhook.py`の`handler`関数を見てねということ
    - `runtime=_lambda.Runtime.PYTHON_3_7`はPython3.7を使ってねということ
- `api`でAPI Gatewayを設定しています。
    - `api.root.add_method("POST", apigw.LambdaIntegration(lambda_func))`でPOSTメソッドを追加、lambda_funcと統合

以上です。あとは下のコマンドでデプロイするだけ。

```shell
$ cdk deploy
```

うまくいくとエンドポイントURLが表示されます。cURLコマンドで適当なJSONをPOSTし、レスポンスを確認してみましょう。


```shell
$ curl -X POST \
> -H "Content-Type: application/json" \ 
> -d '{"Key1":"Value1", "Key2":"Value2"}' \
> https://xxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/prod/

"{\"Key1\":\"Value1\", \"Key2\":\"Value2\"}"
```
上のようにJSONがそのまま返ってきたら成功です。

また、`webhook.py`ではリクエストボディ部を`print(body)`しています。このログは、CloudWatchから確認することができます。AWSのコンソール > サービスから、CloudWatchを見つけてクリックし、ログ > ロググループから`PrintPostStack`の名前のついたログを見ましょう。以下のようにJSONが表示されているはずです。
![スクリーンショット 2020-09-07 6.40.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/476884/570ad615-ed7d-6aad-0394-64587f6632a3.png)

以上です！超単純なAPI Gateway + Lambdaを通してAWS CDKを紹介してみました。
以下の公式の例も参考になると思うのでご覧ください。

- [AWS CDK Intro Workshop > Python Workshop](https://cdkworkshop.com/30-python.html)
- https://github.com/aws-samples/aws-cdk-examples