AWS SAM ローカルを使用したサーバーレスアプリケーション(Golang版)

こちらの公式ドキュメントの「SAM Local によるシンプルなアプリケーションの構築」の項目をGolang版で動かしたメモ。

docs.aws.amazon.com

準備するのは以下の2ファイル

dir/template.yaml
dir/main.go

ビルドと起動

# productsというファイル名でビルド
$ go build -o products 

# AWS SAM Localを起動
$ aws-sam-local local start-api

挙動確認

$ curl http://localhost:3000/products/1
This is a READ operation on product ID 1

$ curl -XDELETE http://localhost:3000/products/11
This is DELETE operation on product ID 11

$ curl -v -XOPTIONS http://localhost:3000/products/1
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 3000 (#0)
> OPTIONS /products/1 HTTP/1.1
> Host: localhost:3000
> User-Agent: curl/7.47.0
> Accept: */*
>
< HTTP/1.1 501 Not Implemented
< Content-Type: application/json
< Date: Sat, 10 Feb 2018 12:01:29 GMT
< Content-Length: 40
<
* Connection #0 to host localhost left intact
Error: unsupported HTTP method (OPTIONS)

ソースコード

それぞれのファイルの中身は以下の通りです。

template.yaml

AWSTemplateFormatVersion : '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Test serverless application.

Resources:
  Products:
    Type: AWS::Serverless::Function
    Properties:
      Handler: products
      Runtime: go1.x
      Events:
        ListProducts:
          Type: Api
          Properties:
            Path: /products
            Method: get
        CreateProduct:
          Type: Api
          Properties:
            Path: /products
            Method: post
        Product:
          Type: Api
          Properties:
            Path: /products/{product}
            Method: any

main.go

package main

import (
    "context"
    "fmt"
    "log"

    "github.com/aws/aws-lambda-go/lambda"
)

type Event map[string]interface{}

func products(ctx context.Context, event Event) (map[string]interface{}, error) {
    res := make(map[string]interface{})
    id := event["pathParameters"].(map[string]interface{})["product"]
    fmt.Printf("%#v\n", event)
    switch event["httpMethod"] {
    case "GET":
        res["body"] = fmt.Sprintf("This is a READ operation on product ID %s", id)
        return res, nil
    case "POST":
        res["body"] = "This is CREATE operation"
        return res, nil
    case "PUT":
        res["body"] = fmt.Sprintf("This is UPDATE operation on product ID %s", id)
        return res, nil
    case "DELETE":
        res["body"] = fmt.Sprintf("This is DELETE operation on product ID %s", id)
        return res, nil
    default:
        errorMessage := fmt.Sprintf("Error: unsupported HTTP method (%s)", event["httpMethod"])
        log.Print(errorMessage)
        res["body"] = errorMessage
        res["statusCode"] = 501
        return res, nil
    }
}

func main() {
    lambda.Start(products)
}