Golangで書いたLambdaとAPI Gateway連携でLambdaプロキシ統合を使う

仕事でGolangを使ったAWS Lambdaスクリプトを書く機会があったんですがLambdaプロキシ統合周りでハマったので備忘録を残しておく。

概要

  • aws-lambda-goを使ってLambdaスクリプトを実装した
  • Lambdaプロキシ統合を有効化するとAPI Gateway経由の通信でパラメータが受け取れなくて困った
  • handlerの引数にAPIGatewayProxyRequestを受け取り APIGatewayProxyResponseを返すことで解決

aws-lambda-goを使ったサンプル

goでLambdaスクリプトを書くのが初めてだったので、まずは公式ドキュメントや社内に落ちてるソースコードを読んでいました。 特に難しいポイントはなく、リクエストとレスポンスに独自のstructを定義してコードを書き進めていました。

package main

import (
    "context"
    "github.com/aws/aws-lambda-go/lambda"
)

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

func handler(ctx context.Context, request MyRequest) (MyResponse, error) {
    ...
    return MyResponse{...}, nil
}

AWS Lambda function handler in Go - AWS Lambda

ところが、この状態でAPI Gatewayに対してHTTPリクエストをしてもrequestオブジェクトの中身が空になってしまいました。
ややこしいことにこの現象はAPI Gateway経由でLambdaを起動した場合にのみ発生し、Lambdaのコンソールのテスト機能を使ってパラメータを渡した場合には再現しないものでした。

Lambdaプロキシ統合の対応

Lambdaプロキシ統合を有効化する場合はリクエストとレスポンスを指定された形式にする必要がありました。

package main

import (
    "context"
    "github.com/aws/aws-lambda-go/events"
    "github.com/aws/aws-lambda-go/lambda"
)

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

func handler(ctx context.Context, request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
    ...
    return events.APIGatewayProxyResponse{Body: string(...), StatusCode: 200}, nil
}

aws-lambda-go/README_ApiGatewayEvent.md at master · aws/aws-lambda-go

分かってしまえばなんてことないんですが、初めて書くgoのLambdaスクリプトが動かない原因がLambdaプロキシ統合と分かるまでに時間がかかりました。