【AWS】Step Functionsによる非同期APIの作り方

普通にLambdaで関数を作成し、API GatewayでWepアプリ化しても、以下の制限により使い物にならない場合がある。

1. API Gatewayの最大タイムアウト30秒以内にレスポンスが無い場合(タイムアウトエラー)
1. Lambdaの最大タイムアウト15分以内に処理が終わらない場合(タイムアウトエラー)

上記にのような問題を、複数のLambdaを並列で実行でき、非同期でレスポンスを返すStep Functionsを使えば解決できる。

![非同期APIgateway.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483556/8f68cd61-a9cb-ac00-a38f-00523fe24048.png)

## 1. IAMロールの作成
1. IAM コンソールでロール -> ロールの作成の順に選択する。
2. AWSサービスを選択し、他の AWS のサービスのユースケース:で、API Gatewayを選択し。次へを押す。
3. 次へを押す。
4. 任意のロール名(例:APIGatewayToStepFunctions)を入力する。
5. ロールを作成を選択する。
6. ロールのリストで、作成したロールの名前を選択し、[Role ARN] (ロール ARN) をメモします。
    arn:aws:iam::123456789012:role/APIGatewayToStepFunctions
7. 許可を追加 -> ポリシーをアタッチを押す。
    ![stepfunction1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483556/7d581abb-439f-945d-b78c-3ff7a89783b6.png)
8. AWSStepFunctionsFullAccessを検索し、チェックを入れて、許可を追加を押す。
    ![stepfunction2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483556/918b5593-bbd2-3126-4dcf-53de0219509d.png)

## 2. Lambda関数の作成
1. Lambda コンソールで関数の作成を押す。
2. 一から作成を選択し、任意の関数の名前を入力し、ランタイムにPython 3.9を選択し、関数の作成を押す。
3. 関数の Amazon Resource Name(ARN) をコピーする。
    arn:aws:lambda:us-east-1:123456789012:function:HelloFunction
![stepfunction3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483556/89c0b0c3-af8b-f89f-e5af-7c1c637b787c.png)

## 3. Step Functionsのステートマシンの作成
1. Step Functions コンソールでステートマシンの作成を押す。
2. ワークフローを視覚的にデザインするで、次へを押す。
    ![stepfunction4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483556/c2c1ca8c-8c2f-8b32-1708-1fa0ce962698.png)
3. 左側のアクションから、AWS Lambda Invokeを「最初の状態をここにドラッグ」へドラッグアンドドロップする。
4. 右側のInspector パネルのAPI パラメータで、Lambda 関数をリストから選択する。
    ![stepfunction5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483556/3dda79e4-cad2-bd84-ea27-7556904537ea.png)
5. 次へを押す。
6. 次へを押す。
7. 任意のステートマシンの名前を入力し、アクセス許可で新しいロールの作成を選択する。
8. ステートマシンの作成を押す。
9. 実行の開始を押し、実行の開始を押す。
10. CloudWatch等で正常にLambdaが実行されたか確認する。

## 4. API GatewayのREST APIの作成
1. Amazon API Gateway コンソールでAPI を作成を押す。
2. REST APIで構築を押す。
3. API名を入力して、APIの作成を押す。
4. アクション -> リソースの作成で、リソース名にexecution と入力する。
5. API Gateway CORS を有効にするにチェックを入れる。
6. リソースを作成を押す。
7. アクション -> メゾッドの作成で、POSTを選択し、チェックを押す。
8. 統合タイプにAWS サービスを選択する。
9. AWS リージョンに任意のリージョン、AWS サービスにStep Functionsを選択する。
10. HTTP メソッドでPOSTを選択する。
11. サクションにStartExecutionを入れる。
12. 実行ロールに1.で作成したIAM ARNを入力する。
    ![stepfunction6.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483556/043f4e99-5150-8790-5399-984403adcc19.png)
13. 保存を押す。
14. 統合リクエストを押す。
15. マッピングテンプレートを開き、テンプレートが定義されていない場合 (推奨)を選択する。
16. マッピングテンプレートの追加を押し、application/jsonもしくはmultipart/form-dataを入れて、チェックを押す。
17. テンプレートの欄に以下を入力する。多くの場合、JSON形式の情報をリクエストするので、以下のマッピングテンプレートを使う。
    ```json:application/json
    #set($input = $input.json('$'))
    {
       "input": "$util.escapeJavaScript($input)",
       "stateMachineArn": "arn:aws:states:ap-northeast-1:000000000000:stateMachine:Get-Amazon-Infomation_StateMachine"
    }
    ```
    Formデータをリクエストする場合、以下のマッピングテンプレートを使用する。
    ```json:multipart/form-data
    #set( $body = $util.escapeJavaScript($input.json('$')) )
    {
      "input": "{\"body\":$body,\"requestContext\":{\"requestId\":\"$context.requestId\"},\"headers\":{\"content-type\":\"$input.params().header.get('content-type')\"}}",
      "stateMachineArn": "arn:aws:states:ap-northeast-1:501273628515:stateMachine:Get-Amazon-Infomation_StateMachine"
    }
    ```
18. 保存を押す。
19. HTTP ヘッダーを開き、ヘッダーの追加を押して、名前=Accept、マッピング元='*/*'と入力する。
20. 統合レスポンス(Integration Response)を押す。
21. ヘッダーマッピング(Header Mappings)にResponse header = Access-Control-Allow-Origin、Mapping value = '*'を入れる。
    ![stepfunction7.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483556/ed3035c3-637b-c752-b08c-2b152ec7af96.png)
22. 戻って、メゾッドレスポンス(Method Response)を押す。
23. Response Headers for 200のNameにAccess-Control-Allow-Originを入れる。
    ![stepfunction8.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483556/641908c0-ce20-7cc4-0b34-41933284a672.png)
24. アクション -> CORSを許可する(Enable CORS)を押して、Enable CORS and replace existing CORS headersを押す。
25. アクション -> APIのデプロイ新しいステージを選択し、ステージ名=devを入れて、デプロイする。
26. ステージ -> POSTを押し、URL の呼び出しのURLから正常に呼び出せるか以下のコマンドで検証する。
```
curl -X POST https://asasdfvsd.execute-api.ap-northeast-1.amazonaws.com/dev/execution -H "Content-Type: application/json" -d "{\"ContentType\": \"applicastion/json\"}"  
```

### 参考文献

https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/tutorial-api-gateway.html

https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html

https://qiita.com/kammy1231/items/c0528fcdb3ee33c3c2b2