在 Go 中为 AWS Lambda 指定多个事件处理程序



通常,Go 中的 AWS Lambda 事件处理程序代码(使用无服务器框架(编码为:

package main
import (
"fmt"
"context"
"github.com/aws/aws-lambda-go/lambda"
)
type MyEvent struct {
Name string `json:"name"`
}
func HandleRequest(ctx context.Context, name MyEvent) (string, error) {
return fmt.Sprintf("Hello %s!", name.Name ), nil
}
func main() {
lambda.Start(HandleRequest)
}

然后,serverless.yml文件包含如下部分:

skeleton-go-get:
name: skeleton-go-get
runtime: go1.x
handler: go-handler  # <- This specifies a file, not a function.
events:
- http:
path: skeleton/go
method: get

那 ^ 创建一个请求处理程序...但现在我希望我的一个 Go 脚本/程序包含 HTTP GET 和 POST 请求的事件处理程序,而不是为每个无服务器函数使用一个 Go 程序文件。

这在 Node.js、Ruby、Python 等语言中是可能的,serverless.yml指定处理程序文件中的哪个函数将用于哪个无服务器函数。例如(对于 Python 函数(:

[...]
functions:
skeleton-python-get:
name: skeleton-python-get
handler: python-handler.handle_get  # <- Specifies the HTTP GET handler.
events:
- http:
path: skeleton/python
method: get
skeleton-python-post:
name: skeleton-python-post
handler: python-handler.handle_post  # <- Specifies the HTTP POST handler.
events:
- http:
path: skeleton/python
method: post

我无法让同样的技巧适用于 Go。我试图在main()中包含正确的请求,但无济于事:

func HandleGetRequest(ctx context.Context, name MyEvent) (string, error) {
return fmt.Sprintf("Hello %s!", name.Name ), nil
}
func HandlePostRequest(ctx context.Context, name MyEvent) (string, error) {
return fmt.Sprintf("Hello %s!", name.Name ), nil
}
func main() {
lambda.Start(HandleGetRequest)
lambda.Start(HandlePostRequest)  // <- Attempt to add another handler.
}

serverless.yml文件中为 Go 处理程序指定多个事件处理程序函数也不起作用:该函数不是处理程序声明的有效部分。

skeleton-go-get:
name: skeleton-go-get
runtime: go1.x
handler: go-handler.HandleGet  # <- Attempt to specify a function.
events:
- http:
path: skeleton/go
method: get
skeleton-go-post:
name: skeleton-go-post
runtime: go1.x
handler: go-handler.HandlePost  # <- Attempt to specify a function.
events:
- http:
path: skeleton/go
method: post

问:如何在一个 Go 程序中包含多个 AWS Lambda 事件处理程序(使用无服务器框架(?

您可以对getpost使用相同的函数(和处理程序(:

skeleton-go:
name: skeleton-go
runtime: go1.x
handler: go-handler
events:
- http:
path: skeleton/go
method: get
- http:
path: skeleton/go
method: post

使用 Go 的内置 HTTP 路由器或使用第三方路由器,例如 Gorilla Mux 或 Chi,如下面的示例代码所示(因为这是我手边的(。从本质上讲,您正在构建一个Go HTTP服务器,但是在Lambda中。因此,请按照设置 Go Web 服务器的详细信息进行操作,并查看 AWS 的 API 网关代理。

package main
import (
"context"
"net/http"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
"github.com/go-chi/chi"
chiproxy "github.com/awslabs/aws-lambda-go-api-proxy/chi"
)
var adapter *chiproxy.ChiLambda
func GetSkeleton(w http.ResponseWriter, r *http.Request) {
...
}
func PostSkeletonToMom(w http.ResponseWriter, r *http.Request) {
...
}
func init() {
r := chi.NewRouter()
r.Get("/skeleton/go", GetSkeleton)
r.Post("/skeleton/go", PostSkeletonToMom)
adapter = chiproxy.New(r)
}
func lambdaHandler(ctx context.Context, req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
c, err := adapter.ProxyWithContext(ctx, req)
return c, err
}
func main() {
lambda.Start(lambdaHandler)
}

您不需要在 Lambda 中为自己构建 Go 服务器,因为您已经从无服务器框架为您提供了 API 网关......

我使用了AWS CloudFormation + SAM,我使用了HTTP API Gateway(不是REST(,但它应该以类似的方式运行。

首先。。。您需要将其转换为 1 个 Lambda 函数,用于 2 个事件,如下所示:

skeleton-go-get:
name: skeleton-go-get
runtime: go1.x
handler: go-handler  # <- This specifies a file, not a function.
events:
- http:
path: skeleton/go
method: get
- http:
path: skeleton/go
method: post

在您的 lambda 中,您应该拥有:

package main
import ...
func getSkeleton(event events.APIGatewayV2HTTPRequest) (events.APIGatewayV2HTTPResponse, error) {
// Return APIGateway Response
}
func postSkeleton(event events.APIGatewayV2HTTPRequest) (events.APIGatewayV2HTTPResponse, error) {
// Return APIGateway Response
}
func handler(_ context.Context, event events.APIGatewayV2HTTPRequest) (events.APIGatewayV2HTTPResponse, error) {
// Log Events
eventJson, _ := json.Marshal(event)
log.Printf("EVENT: %s", string(eventJson))
switch event.RouteKey {
case "GET /skeleton/go":
return getSkeleton(event)
case "POST /skeleton/go":
return postSkeleton(event)
default:
return events.APIGatewayV2HTTPResponse{
StatusCode: 400
}, nil
}
}
func main() {
lambda.Start(handler)
}

最新更新