aws-nodejs-typescriptで作成したlambdaを使ってStep Functionsを構築したらハマったこと

# はじめに

`ServerlessFramework`の`aws-nodejs-typescript`テンプレートを使って構築したlambdaを使った`Step Functions`を構築した時にエラーになったので、修正内容をメモ。


# Step Functionsとは

こちらの記事がわかりやすい

https://qiita.com/miyuki_samitani/items/6c58d107cdc86d938fe3

# Step Funcitons構築


1. sls create

    ```bash
    sls create --template aws-nodejs-typescript
    ```

    これで以下ファイルが生成される
    
    ```bash
    $ tree -L 1
    .
    ├── README.md
    ├── node_modules
    ├── package.json
    ├── pnpm-lock.yaml
    ├── serverless.ts
    ├── src
    ├── tsconfig.json
    └── tsconfig.paths.json
    ```

1. Plugin: `serverless-step-functions`のインストール
    
    ```typescript:serverless.yml
      service: 'step-functions',
      frameworkVersion: '3',
    　　　　// serverless-step-functions追加
      plugins: ['serverless-esbuild', 'serverless-step-functions'],
      provider: {
        name: 'aws',
        runtime: 'nodejs14.x',
    ```
    
    ```bash
    serverless plugin install -n serverless-step-functions
    ```

1. serverless.tsの修正

    今回は試しとして、lambdaが１つだけある構成で作ってみる。
    lambdaは`POST: hellow`がすでに作られているので、それを使う。
    
    構成
    <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985550/fd542edd-de4f-f72d-4f57-08e76739c496.png" width="400"></img>
    
    公式から例を拾ってくる
    
    ```yaml:serverless.yml
    stepFunctions:
      stateMachines:
        hellostepfunc1:
          events:
            - http:
                path: gofunction
                method: GET
          name: myStateMachine
          definition:
            Comment: "A Hello World example of the Amazon States Language using an AWS Lambda Function"
            StartAt: HelloWorld1
            States:
              HelloWorld1:
                Type: Task
                Resource:
                  Fn::GetAtt: [hello, Arn]
                End: true
    ```
    
    これを`POST`にし、corsを有効にして、`serverless.tsに書き直すと↓のようになる。

    ただし、Commentは使えなかったので外しています。
    
    ```typescript:serverless.ts
      stepFunctions: {
        stateMachines: {
          hellostepfunc1: {
            events: [{
              http: {
                path: 'gofunction',
                method: 'POST',
                cors: {
                  origin: "*",
                  headers: [
                    "Content-Type",
                    "X-Amz-Date",
                    "Authorization",
                    "X-Api-Key",
                    "X-Amz-Security-Token",
                    "X-Amz-User-Agent"
                  ]
                }
              }
            }],
            name: 'myStateMachine',
            definition: {
              Commnet: "A Hello World example of the Amazon States Language using an AWS Lambda Function",
              StartAt: 'HelloWorld1',
              States: {
                HelloWorld1: {
                  Type: 'Task',
                  Resource: {
                    'Fn::GetAtt': ['hello', 'Arn']
                  },
                  End: true
                }
              }
            }
          }
        }
      }
    ```

1. デプロイ

    ```bash
    sls deploy
    
    ・・・
    
    ✔ Serverless StepFunctions OutPuts
    endpoints:
      POST - https://************.execute-api.us-east-1.amazonaws.com/dev/gofunction
    ```

1. POSTリクエストを送ってみる
        
    ```bash
    $ curl -X POST -H "Content-Type: application/json" -d '{"name":"太郎"}' https://***********.execute-api.us-east-1.amazonaws.com/dev/gofunction
    
    {"executionArn":"arn:aws:states:us-east-1:**********:execution:myStateMachine:***************-*******","startDate":1.67637299142E9}
    ```
        
    それらしいレスポンスが帰ってきた

1. マネジメントコンソールから実行結果を確認してみる

    ![スクリーンショット 2023-02-14 1.49.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985550/829c7fb7-95fc-5c1d-790c-81c34d66ea6e.png)

    <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985550/c3bafe80-0733-af4c-ef52-82b7919c1256.png" width="250"></img>


    <font color="red">失敗していた</font>


# 失敗の原因調査

step functionsでは失敗のログが出力されるので、それを確認すると、

```json:Type
{
  "errorType": "TypeError",
  "errorMessage": "Cannot read property 'Content-Type' of undefined",
  "trace": [
    "TypeError: Cannot read property 'Content-Type' of undefined",
    "    at httpJsonBodyParserMiddlewareBefore (/node_modules/.pnpm/@middy+http-json-body-parser@3.6.2/node_modules/@middy/http-json-body-parser/index.js:13:29)",
    "    at runMiddlewares (/node_modules/.pnpm/@middy+core@3.6.2/node_modules/@middy/core/index.js:118:27)",
    "    at runRequest (/node_modules/.pnpm/@middy+core@3.6.2/node_modules/@middy/core/index.js:78:15)",
    "    at Runtime.middy2 (/node_modules/.pnpm/@middy+core@3.6.2/node_modules/@middy/core/index.js:32:16)",
    "    at Runtime.handleOnceNonStreaming (/var/runtime/Runtime.js:74:25)"
  ]
}
```

このように出ており、`middy`で`Content-Type`が`undefined`に対して呼ばれているようでした。

実際にlambdaのコードを見てみると、この部分でした。👇

```typescript
  const httpJsonBodyParserMiddlewareBefore = async (request) => {
    const { headers, body } = request.event;
    // headersがundefinedになっていた
    const contentType = headers["Content-Type"] ?? headers["content-type"];
```

> #### middyとは
> 「AWS Lambda 向け軽量Node.jsミドルウエアエンジン」と紹介されていました。
詳しくは調べてみてください。


# 修正

step functionsのlambaでは、headersやbodyが`undefined`になってしまうため、
middyは使わないように直してあげれば良さそうです。

```typescript:handler.ts
const hello = async (event) => {
  return {
    message: `Hello ${event.body.name}, welcome to the exciting Serverless world!`,
    event,
  };
};

export const main = hello;
```

## 再度POSTリクエストを送ってみる
        
```bash
$ curl -X POST -H "Content-Type: application/json" -d '{"name":"太郎"}' https://***********.execute-api.us-east-1.amazonaws.com/dev/gofunction

{"executionArn":"arn:aws:states:us-east-1:**********:execution:myStateMachine:***************-*******","startDate":1.67637299142E9}
```

![スクリーンショット 2023-02-14 20.12.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985550/b5487f87-4aca-49d5-0482-5f719b8b329c.png)
        
### 成功！

入出力もコンソールから確認できて良い感じですね

![スクリーンショット 2023-02-14 20.13.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985550/5c44d80a-2120-3760-1d25-30a2b5c323a8.png)