I have code copied directly from the go section of the lambda tutorial
package main
import (
"context"
"encoding/json"
"fmt"
"log"
"github.com/aws/aws-lambda-go/lambda"
)
type MyEvent struct {
Name string `json:"name"`
Age int `json:"age"`
}
type MyResponse struct {
Message string `json:"Answer"`
}
func HandleLambdaEvent(ctx context.Context, event MyEvent) (MyResponse, error) {
// event
eventJson, _ := json.MarshalIndent(event, "", " ")
log.Printf("EVENT: %s", eventJson)
return MyResponse{Message: fmt.Sprintf("%s is %d years old!", event.Name, event.Age)}, nil
}
func main() {
lambda.Start(HandleLambdaEvent)
}
I have created a .zip file, a role, attached that role and created the function on lambda.
I can invoke the function with aws lambda successfully
# aws lambda invoke --function-name my-function --cli-binary-format raw-in-base64-out --payload '{"name": "Kevin", "age":62}' output.txt
# cat output.txt
{"Answer":"Kevin is 62 years old!"}
I created a function URL and can call it via awscurl (or curl)
# curl -X POST https://XXXXXXXXXX.lambda-url.us-east-1.on.aws/ \
-H 'Content-type: application/json' \
--user AWS_ID:AWS_KEY \
--aws-sigv4 "aws:amz:us-east-1:lambda \
-d '{"Name": "Kevin", "Age": 62}'
But the json doesn't go to the function (verified from the logs) and so isn't processed by my-function
{"Answer":" is 0 years old!"}
I have futzed with lambda:InvokeFunctionURL but this didn't make any difference
Update: I changed my HandleLambdaRequest function quite a bit, see below
func HandleLambdaEvent(ctx context.Context, request map[string]interface{}) (MyResponse, error) {
// event
jsonStr, err := json.Marshal(request)
if err != nil {
return MyResponse{Message: "can't unmarshal request"}, nil
}
var event Event
if err = json.Unmarshal(jsonStr, &event); err != nil {
return MyResponse{Message: err.Error()}, nil
}
if event.Name == "" {
var apigate events.APIGatewayV2HTTPRequest
if err = json.Unmarshal(jsonStr, &apigate); err != nil {
return MyResponse{Message: "can't get event or request"}, nil
}
body := []byte(apigate.Body)
if err = json.Unmarshal(body, &event); err != nil {
return MyResponse{Message: "can't unmarshal api.Body"}, nil
}
return MyResponse{Message: fmt.Sprintf("url %s:%d", event.Name, event.Age)}, nil
}
return MyResponse{Message: fmt.Sprintf("invoke %s:%d", event.Name, event.Age)}, nil
}
Lambda handles your request differently when you invoke the function through a function URL! This is not very intuitive, especially for people who are not familiar with the lambda integration in the Amazon API Gateway service, and I hope they make this more clear in the documentation. Here is the request and response payload structures. In your case, the POST payload is mapped to event.Body, and you need to define "body" in the "MyEvent" struct like this,
type MyEvent struct {
...
Body string `json:body`
}
Hope this helps.
MyEvent does not match the payload your Lambda is actually receiving. When invoked via a Function URL, your Lambda receives an event with the shape of an API Gateway request.
The github.com/aws/aws-lambda-go package contains the request and response types for the various Lambda invoke events. APIGatewayV2HTTPRequest is the one you're looking for. Your POST payload is in Body.
type APIGatewayV2HTTPRequest struct {
Version string `json:"version"`
RouteKey string `json:"routeKey"`
RawPath string `json:"rawPath"`
RawQueryString string `json:"rawQueryString"`
Cookies []string `json:"cookies,omitempty"`
Headers map[string]string `json:"headers"`
QueryStringParameters map[string]string `json:"queryStringParameters,omitempty"`
PathParameters map[string]string `json:"pathParameters,omitempty"`
RequestContext APIGatewayV2HTTPRequestContext `json:"requestContext"`
StageVariables map[string]string `json:"stageVariables,omitempty"`
Body string `json:"body,omitempty"`
IsBase64Encoded bool `json:"isBase64Encoded"`
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With