curl请求到AWS Lambda函数没有接收到JSON数据。

huangapple go评论93阅读模式
英文:

curl request to AWS lambda function receives no json

问题

我直接从Lambda教程的Go部分复制了代码:

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)
}

我创建了一个.zip文件,一个角色,并将该角色附加到Lambda函数上。
我可以成功地使用aws lambda调用该函数:

# 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!"}

我创建了一个函数URL,并可以通过awscurl(或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}' 

但是JSON数据没有传递给函数(从日志中验证),因此没有被my-function处理:

{"Answer":" is 0 years old!"}

我已经尝试过调整lambda:InvokeFunctionURL,但没有任何改变。

更新:我对HandleLambdaRequest函数进行了相当大的更改,如下所示:

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
}

以上是你提供的代码的翻译。

英文:

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
}

答案1

得分: 2

Lambda在通过函数URL调用函数时会以不同的方式处理您的请求!对于不熟悉Amazon API Gateway服务中Lambda集成的人来说,这并不直观,希望文档中能更清楚地说明这一点。这里是请求和响应负载结构。在您的情况下,POST负载映射到event.Body,您需要像这样在"MyEvent"结构中定义"body",

type MyEvent struct {
    ...
    Body string `json:body`
}

希望对您有所帮助。

英文:

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.

答案2

得分: 1

MyEvent与您的Lambda实际接收到的有效负载不匹配。当通过函数URL调用时,您的Lambda会接收到一个具有API Gateway请求形状的事件。

github.com/aws/aws-lambda-go包含各种Lambda调用事件的请求和响应类型。APIGatewayV2HTTPRequest是您要查找的类型。您的POST有效负载位于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"`
}
英文:

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

huangapple
  • 本文由 发表于 2022年12月17日 00:46:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/74827422.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定