AWS SAM ローカルでいろんな角度からhello worldする

## やりたいこと
サーバーレスな処理を実装するのに備えて、ひとまずSAMを使ってローカル環境にてブラウザやcurlコマンドでhello worldをしたいです。

```
$ sam --version
SAM CLI, version 1.22.0
```

## 実装！
### sam initする

`sam init`して、プロジェクトを新規作成します。
SAMからの質問に対して、下のように答えました。

```
template: AWS Quick Start Templates
package: type: Zip (artifact is a zip uploaded to S3)
runtime: ruby2.7
Project name [sam-app]: identify_user
quick start application templates: Hello World Example
```

↓（参考）上記の詳細、質疑応答の全貌。

```
$ sam init

Which template source would you like to use?
	1 - AWS Quick Start Templates
	2 - Custom Template Location
Choice: 1
What package type would you like to use?
	1 - Zip (artifact is a zip uploaded to S3)
	2 - Image (artifact is an image uploaded to an ECR image repository)
Package type: 1

Which runtime would you like to use?
	1 - nodejs14.x
	2 - python3.8
	3 - ruby2.7
	4 - go1.x
	5 - java11
	6 - dotnetcore3.1
	7 - nodejs12.x
	8 - nodejs10.x
	9 - python3.7
	10 - python3.6
	11 - python2.7
	12 - ruby2.5
	13 - java8.al2
	14 - java8
	15 - dotnetcore2.1
Runtime: 3

Project name [sam-app]: identify_user

AWS quick start application templates:
	1 - Hello World Example
	2 - Step Functions Sample App (Stock Trader)
Template selection: 1

    -----------------------
    Generating application:
    -----------------------
    Name: identify_user
    Runtime: ruby2.7
    Dependency Manager: bundler
    Application Template: hello-world
    Output Directory: .

    Next steps can be found in the README file at ./identify_user/README.md

```

### Lambdaとtemplate.yamlを編集

Hello worldするためのLambdaとtemplate.yamlを整えます。
この後、AWS Rekognitionで顔認証するという個人的な事情で、Lambdaは`IdentifyUserFunction`という関数名にしました。

```ruby:app.rb
require 'json'

def lambda_handler(event:, context:)
  message = 'hello world'

  { 
    statusCode: 200,
    body: {
      message: message
    }.to_json
  }
end
```

```yaml:template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  identify_user

  Sample SAM Template for identify_user

Globals:
  Function:
    Runtime: ruby2.7
    Timeout: 30

Resources:
  IdentifyUserFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: identify_user/
      Handler: app.lambda_handler
      Runtime: ruby2.7
      Events:
        IdentifyUser:
          Type: Api
          Properties:
            Path: /identify_user
            Method: get
```

### ローカルで動作確認

SAMのサーバーをローカルで起動します。（そう、サーバーレスなのに。）
ポート番号は指定しないと3000になるのですが、僕の場合はRailsサーバーを3000で動かしていたので、`-p 3001`とオプションで3001を指定。

```
sam local start-api -p 3001
```

#### ブラウザで動作確認

ブラウザで`http://127.0.0.1:3001/identify_user`にアクセス。

>{
message: "hello world"
}

↑うまく行くとブラウザにこう表示されます。

>{
message: "Missing Authentication Token"
}

↑なんか間違えているとこんなのが帰ってきます。
例えばtemplate.yamlにてLambdaが`method: post`になってるとか:see_no_evil:


#### curlで動作確認

curlとは？client for urlの略らしいです。
公式？　https://curl.se/
e-words https://e-words.jp/w/CURL.html

次にcurlでパラメーターを渡してAPIを呼び出しても、きちんと動作するかを確認していきます。

が、まずはとりまパラーメーター無しでGETでcurlを実行してみます。

##### とりまパラメーター無しでcurlでhello world

```terminal
curl -X GET http://127.0.0.1:3001/identify_user

// {"message":"hello world"}%
```

きちんと返ってきました！
末尾の`%`がよくわからんが、まぁいいか。。

##### いよいよcurlでパラメーターを渡してhello world

ここでは、メソッドをPOSTに変更します。
なんかよくわからないけど、自分のメモにunixtimeも残ってたのでそれも渡してみます。

```ruby:app.rb
require 'json'

def lambda_handler(event:, context:)
  # 追加。パラーメーターを取得する
  params = JSON.parse(event['body'], symbolize_names: true)

  { 
    statusCode: 200,
    body: {
      message: params[:message],
      unixtime: params[:unixtime]
    }.to_json
  }
end
```

```yaml:template.yaml
Resources:
  UpdateAttendanceResultFunction:
    Type: AWS::Serverless::Function
    Properties:
      （中略）
      Events:
        HelloWorld:
          Type: Api
          Properties:
            Path: /hello_world
            Method: post # ここをちゃんと変更！
```

で、実行。

```
curl -X POST --data '{"message":"hello world", "unixtime": 1634532494}' http://127.0.0.1:3001/identify_user

// {"message":"hello world","unixtime":1634532494}% 
```

きちんと返してくれています。

ちなみにここまでローカルで確認するだけなら、`sam deploy`はもちろん、`sam build`も必要ないです。

## 最後に
これはサーバーレスにRekognitionに問い合わせをするという自分の過去の課題のSAM部分です。
Rekognition部分に関しては、弊社ブログにまとめました↓

https://tech.fusic.co.jp/posts/2021-11-26-search-faces-by-image/