AWS Lambda + Node.js で Hello World

## 概要

- AWS (Amazon Web Services) Lambda で Node.js によるシンプルな Hello World を動かす

## Lambda 関数の作成

[Lambda Management Console](https://console.aws.amazon.com/lambda/) から Lambda 関数を作成する。

「一から作成」を選択。

<img width="562" alt="aws-lambda-1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/0c8a31e1-33b3-eedb-4ae9-1bdc91d36d1e.png">

「基本的な情報」を入力する。
関数名: 任意の名前
ランタイム: Node.js 10.x
実行ロール: 基本的な Lambda アクセス権限で新しいロールを作成

<img width="971" alt="aws-lambda-2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/df532d76-9e76-a2b0-524e-d9d4a5a76cde.png">

「Designer」では特に何もしない。

<img width="980" alt="aws-lambda-3.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/cf4c70d1-61a4-c472-e7d7-cfbb48d92179.png">

「関数コード」を入力する(デフォルト値のまま)。
コード エントリ タイプ: コードをインラインで編集
ランタイム: Node.js 10.x
ハンドラ: index.handler

<img width="948" alt="aws-lambda-4.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/92773464-666d-8792-fc7a-0a836c34fe2d.png">

index.js は以下を入力する。

```index.js
exports.handler = async (event, context) => {

    const response = {

        foo: 'Hello, world',
        bar: 'Goodbye, world',
        event: event, // 呼び出し元からの情報を見たいので出力に含める
        context: context, // コンテキスト情報を見たいので出力に含める

        // Amazon API Gateway を利用して Lambda 関数を WebAPI 化するときは
        // 必要に応じて isBase64Encoded, statusCode, headers, body をセットする。
        // 今回は不要だがサンプル的にセットしておく。
        statusCode: 200, // HTTP 200 OK
        headers: {
            'x-custom-header': 'my custom header value'
        },
        body: JSON.stringify({
            foo: 'Hello, world',
            bar: 'Goodbye, world',
        })
    };

    return response;
};
```

ページ右上の「テスト」をクリックして、新しいテストイベントを作成する。
イベントテンプレート: Hello World
イベント名: 任意の名前
入力データとなる JSON は任意のものに変更する(あるいはデフォルトのまま)。

<img width="833" alt="aws-lambda-5.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/0417cb01-6ff7-70c9-fd15-9b398f4221a3.png">

ページ右上の「テスト」をクリックすると、テストを実行できる。結果が表示される。

<img width="955" alt="aws-lambda-6.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/b234c28d-3740-d0c8-77f6-1008e7e4a0b9.png">

出力結果の例。

```json
{
  "foo": "Hello, world",
  "bar": "Goodbye, world",
  "event": {
    "key1": "value1",
    "key2": "value2",
    "key3": "value3"
  },
  "context": {
    "callbackWaitsForEmptyEventLoop": true,
    "functionVersion": "$LATEST",
    "functionName": "myNodeJsHelloWorld",
    "memoryLimitInMB": "128",
    "logGroupName": "/aws/lambda/myNodeJsHelloWorld",
    "logStreamName": "2019/08/24/[$LATEST]XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    "invokedFunctionArn": "arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:myNodeJsHelloWorld",
    "awsRequestId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
  },
  "statusCode": 200,
  "headers": {
    "x-custom-header": "my custom header value"
  },
  "body": "{\"foo\":\"Hello, world\",\"bar\":\"Goodbye, world\"}"
}
```

## ハンドラー関数に渡される引数について

ハンドラー関数には event オブジェクトと context オブジェクトが渡される。

[Node\.js による Lambda 関数のビルド \- AWS Lambda](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/programming-model.html)

> index.js ファイルは、イベントオブジェクトおよびコンテキストオブジェクトを取得する handler という名前の関数をエクスポートします。この関数は、呼び出されると Lambda によって呼び出されるハンドラ関数です。Node.js 関数のランタイムは、Lambda から呼び出しイベントを取得し、ハンドラに渡します。関数設定で、ハンドラ値は index.handler です。

[Node\.js の AWS Lambda 関数ハンドラー \- AWS Lambda](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/nodejs-prog-model-handler.html)

> ランタイムでは、ハンドラーメソッドに 3 つの引数を渡します。最初の引数は、呼び出し元からの情報を含む event オブジェクトです。呼び出し元は、呼び出しを呼び出すときにこの情報を JSON 形式の文字列として渡します。AWS のサービスで関数を呼び出す場合、そのイベント構造はサービスによって異なります。
> 2 番目の引数は、コンテキストオブジェクトです。この引数には、呼び出し、関数、および実行環境に関する情報が含まれます。前述の例では、関数は、コンテキストオブジェクトからログストリームの名前を取得し、それを呼び出し元に返します。
> 3 番目の引数 callback は、レスポンスを送信するために non-async 関数で呼び出すことができる関数です。コールバック関数は、Error とレスポンスの 2 つの引数を取ります。応答オブジェクトは、JSON.stringify と互換性がある必要があります。
> 非同期関数の場合は、callback を使用する代わりに、レスポンス、エラー、または promise をランタイムに返します。

[他のサービスで AWS Lambda を使用する \- AWS Lambda](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/lambda-services.html)

> Lambda と統合する各サービスでは、データが JSON の関数にイベントとして送信されます。イベントドキュメントの構造はイベントタイプごとに異なり、関数をトリガーしたリソースまたはリクエストに関するデータが含まれています。Lambda ランタイムは、イベントをオブジェクトに変換し、それを関数に渡します。

[Node\.js での AWS Lambda Context オブジェクト \- AWS Lambda](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/nodejs-prog-model-context.html)

> Lambda で関数が実行されると、コンテキストオブジェクトはハンドラーに渡されます。このオブジェクトは、呼び出し、関数、および実行関数に関する情報を示すメソッドおよびプロパティを提供します。

## 参考資料

- [コンソールで Lambda 関数を作成する \- AWS Lambda](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/getting-started-create-function.html)
- [Node\.js による Lambda 関数のビルド \- AWS Lambda](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/programming-model.html)
- [チュートリアル: Lambda プロキシ統合による Hello World API の構築 \- Amazon API Gateway](https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/api-gateway-create-api-as-simple-proxy-for-lambda.html)
- [API Gateway で Lambda エラーを処理する \- Amazon API Gateway](https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/handle-errors-in-lambda-integration.html)