Home > database >  curl request to AWS lambda function receives no json
curl request to AWS lambda function receives no json

Time:12-17

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

CodePudding user response:

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.

CodePudding user response:

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"`
}
  • Related