はじめに
API GatewayとLambdaの統合には様々な実装パターンがあるせいか、下記の状況下でのルーティングの方法の情報が無かったので投稿します。
前提
- すべてのメソッドを単一のLambda関数とプロキシ統合する
- プロキシリソース(
{proxy+}
)は使わない(HTTPルーティングはAPI Gatewayで行う) - aws-lambda-web-adapterやaws-lambda-go-api-proxyなどは、使用しない
結論
Lambda関数が受け取るeventオブジェクトに含まれるresource
とhttpMethod
を使用する。
path
も使えそうですが、実際のパラメータが含まれる値のため、使用しない方が良いでしょう。
event
{
"resource": "/todo/{id}",
"path": "/todo/123",
"httpMethod": "GET",
...
}
Goによるサンプル実装
main.go
package main
import (
"context"
"fmt"
"net/http"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
)
func Handler(ctx context.Context, event *events.APIGatewayProxyRequest) (*events.APIGatewayProxyResponse, error) {
if event == nil {
return nil, fmt.Errorf("event is null")
}
switch mr := event.HTTPMethod + " " + event.Resource; mr {
case "GET /todo":
return listTodoHandler(ctx, event)
case "GET /todo/{id}":
return getTodoHandler(ctx, event)
case "POST /todo":
return createTodoHandler(ctx, event)
default:
return nil, fmt.Errorf(`handler is not found: %s`, mr)
}
}
リソース・メソッドで二段階の分岐や、文字列を関数化する等も良いかもしれません。
私自身は、逆に見通しが悪くなるように感じたので、単純な実装に留めました。
補足
メソッドリクエストの設定から、オペレーション名を設定することで、event内のrequestContext
にoperationName
が付与されます。こちらの値を使ってルーティングすることも可能です。
(当初は、こちらの方法を利用しようと思っていました。)
しかし、オペレーション名は任意項目であることに加え、複数のメソッドに同一の値を設定できてしまうことから、こちらの値を使用しない方が良いと判断しました。
(オペレーション名は、OpenAPIのoperationId
に対応する値なので、OpenAPI Spec 同様にユニーク制約があればよかったのですが)