无法从Amazon API网关将参数从POST传递给Golang AWS Lambda

3
与此不同的是 - 如何从 Amazon API Gateway 将参数传递给 AWS Lambda。因为我能够在 API Gateway 中转换参数,但无法在 Golang 中传递或打印它。然而,对于 Python 来说,相同的 API Gateway 可以正常工作。

以下是我的 API Gateway 和 AWS Lambda(Golang)的日志。我可以看到 POST 参数已成功转换为 JSON。尽管如此,在 Lambda 函数日志中仍然无法看到它。

API Gateway 日志

(442f74ed-39e5-4372-bf85-42bf814f802f) Extended Request Id: EIaYxxMF3lQ=
(442f74ed-39e5-4372-bf85-42bf814f802f) Method request path: {}

(442f74ed-39e5-4372-bf85-42bf814f802f) Method request query string:    {}

(442f74ed-39e5-4372-bf85-42bf814f802f) Method request headers: {Accept=*/*, Cache-Control=max-age=259200, X-Twilio-Signature=ZWg2v7xxxfnBlPyxE=, User-Agent=TwilioProxy/1.1, X-Forwarded-Proto=https, I-Twilio-Idempotency-Token=e5d1xxx221bc4, X-Forwarded-For=54.xxxx.227, Host=xxxxxxx.execute-api.us-east-1.amazonaws.com, X-Forwarded-Port=443, X-Amzn-Trace-Id=Root=1-5de67103-7994dbxxx0dbd872, Content-Type=application/x-www-form-urlencoded}}  

(442f74ed-39e5-4372-bf85-42bf814f802f) Method request body before transformations: ToCountry=US&ToState=UT&SmsMessageSid=SMed65axxx595c7938df&NumMedia=0&ToCity=&FromZip=&SmsSid=SMed65aa5xxccdd595c7938df&FromState=&SmsStatus=received&FromCity=&Body=Testing+again&FromCountry=IN&To=%2Bxxxx848&ToZip=&NumSegments=1&MessageSid=SMed65axxxd595c7938df&AccountSid=AC23a2cbxxx65a66d98&From=%2B9xxxx5590&ApiVersion=2010-04-01

(442f74ed-39e5-4372-bf85-42bf814f802f) Endpoint request URI: https://lambda.us-east-1.amazonaws.com/2015-03-31/functions/arn:aws:lambda:us-east-1:6xxxxxxxx6:function:Twillio_connector_test/invocations

(442f74ed-39e5-4372-bf85-42bf814f802f) Endpoint request headers: {x-amzn-lambda-integration-tag=442f74ed-39e5-4372-bf85-42bf814f802f, Authorization=*****27aa7a, X-Amz-Date=20191203T142819Z, x-amzn-apigateway-api-id=xxxxx, X-Amz-Source-Arn=arn:aws:execute-api:us-east-1:69xxxx886:xxxxxxx/v1/POST/message, Accept=application/x-www-form-urlencoded, User-Agent=AmazonAPIGateway_f7504e7yc6, X-Amz-Security-Token=IQoJbxxxhQH [TRUNCATED]

(442f74ed-39e5-4372-bf85-42bf814f802f) Endpoint request body after transformations: 
    {
        "ToCountry": "US",
        "ToState": "UT",
        "SmsMessageSid": "SMed65aaxxxxxx5c7938df",
        "NumMedia": "0",
        "ToCity": "",
        "FromZip": "",
        "SmsSid": "SMed65aaxxxxxx938df",
        "FromState": "",
        "SmsStatus": "received",
        "FromCity": "",
        "Body": "Testing+again",
        "FromCountry": "IN",
        "To": "%2B1xxxxxx848",
        "ToZip": "",
        "NumSegments": "1",
        "MessageSid": "SMed65aa5dxxxx7938df",
        "AccountSid": "AC23xxxd98",
        "From": "%2B9xxxxxx90",
        "ApiVersion": "2010-04-01"
    }

(442f74ed-39e5-4372-bf85-42bf814f802f) Endpoint response headers: {Date=Tue, 03 Dec 2019 14:28:20 GMT, Content-Type=application/json, Content-Length=43, Connection=keep-alive, x-amzn-RequestId=168394b7-c152-4434-af02-03a03b6f3090, x-amzn-Remapped-Content-Length=0, X-Amz-Executed-Version=$LATEST, X-Amzn-Trace-Id=root=1-5de67103-7994dbxxxxbe30dbd872;sampled=0}

(442f74ed-39e5-4372-bf85-42bf814f802f) Endpoint response body before transformations: "Lambda function is completed successfully"

(442f74ed-39e5-4372-bf85-42bf814f802f) Method response body after transformations: Lambda function is completed successfully

(442f74ed-39e5-4372-bf85-42bf814f802f) Method response headers: {X-Amzn-Trace-Id=Root=1-5de67103-7994dbxxxxxxd872;Sampled=0, Content-Type=application/xml}

Lambda函数代码

func Handler(request events.APIGatewayProxyRequest) (string, error) {

    fmt.Println("request:", events.APIGatewayProxyRequestContext)
    fmt.Println("request:", events.APIGatewayProxyResponse)
    fmt.Println("request:", events.APIGatewayRequestIdentity)

    fmt.Printf("%+v\n", request)
    fmt.Println("request Body:", request.Body)
    fmt.Println("request HTTPMethod:", request.HTTPMethod)
    fmt.Println("request Headers:", request.Headers)
    fmt.Println("request:", request.RequestContext.RequestID)

    fmt.Println("PrettyPrint")
    prettyPrint(request)

Lambda函数日志

request: {   map[] map[] map[] map[] map[] map[] {    {           }  map[]  } Good Day false}
{Resource: Path: HTTPMethod: Headers:map[] MultiValueHeaders:map[] QueryStringParameters:map[] MultiValueQueryStringParameters:map[] PathParameters:map[] StageVariables:map[] RequestContext:{AccountID: ResourceID: Stage: RequestID: Identity:{CognitoIdentityPoolID: AccountID: CognitoIdentityID: Caller: APIKey: AccessKey: SourceIP: CognitoAuthenticationType: CognitoAuthenticationProvider: UserArn: UserAgent: User:} ResourcePath: Authorizer:map[] HTTPMethod: APIID:} Body:Good Day IsBase64Encoded:false}
request Body: Good Day
request HTTPMethod: 
request Headers: map[]
request: 

我已经尝试了许多方法,但是在Golang代码中无法获取所需的参数。如果我做错了什么,请纠正我。任何帮助将不胜感激。
PS:我使用了这份文档作为设置API Gateway的参考 - https://www.twilio.com/docs/sms/tutorials/how-to-receive-and-reply-python-amazon-lambda。该设置对于Python Lambda函数运行良好。

我认为你的 Handler 函数签名是错误的,它应该有两个参数,即 ContextAPIGatewayProxyRequest。尝试更改一下,这样应该会有所帮助。此外,你的返回值应该是 (APIGatewayProxyResponse, error) - Arun Poudel
@ArunPoudel 感谢您的评论。我也尝试了以下带有“Context”参数的代码。但是,我仍然没有得到所需的参数。 func Handler(ctx context.Context, request events.APIGatewayProxyRequest) (string, error) { - Rahul Satal
你能否分享一下你的CloudFormation模板或者API网关的设置方式? - Arun Poudel
@ArunPoudel 我已经使用这份文档作为API Gateway的设置参考 - https://www.twilio.com/docs/sms/tutorials/how-to-receive-and-reply-python-amazon-lambda。正如文档中所述,对于Python Lambda函数,设置也可以正常工作。 - Rahul Satal
我注意到请求正文显示“Good Day”。这个词从哪里来的?我猜它可能会给我们带来灵感? - Sky.Li
显示剩余2条评论
1个回答

1

结论:

这个问题是由于Golang和Python中Lambda处理程序的不同参数结构引起的。

细节:

  • 由API Gateway映射模板生成的JSON:
    {
        "ToCountry": "US",
        "ToState": "UT",
        "SmsMessageSid": "SMed65aaxxxxxx5c7938df",
        "NumMedia": "0",
        "ToCity": "",
        "FromZip": "",
        "SmsSid": "SMed65aaxxxxxx938df",
        "FromState": "",
        "SmsStatus": "received",
        "FromCity": "",
        "Body": "Testing+again",
        "FromCountry": "IN",
        "To": "%2B1xxxxxx848",
        "ToZip": "",
        "NumSegments": "1",
        "MessageSid": "SMed65aa5dxxxx7938df",
        "AccountSid": "AC23xxxd98",
        "From": "%2B9xxxxxx90",
        "ApiVersion": "2010-04-01"
    }
  • Python中的event参数:
    def lambda_handler(event, context):
        print("Received event: " + str(event))
        return '<?xml version=\"1.0\" encoding=\"UTF-8\"?>'\
           '<Response><Message>Hello world! -Lambda</Message></Response>'

参考 AWS Python Doc:

event - AWS Lambda使用此参数将事件数据传递给处理程序。此参数通常是Python dict类型。它也可以是列表、str、int、float或NoneType类型。

  • [重要部分] golang中的events.APIGatewayProxyRequest参数:
// APIGatewayProxyRequest contains data coming from the API Gateway proxy
type APIGatewayProxyRequest struct {
    Resource                        string                        `json:"resource"` // The resource path defined in API Gateway
    Path                            string                        `json:"path"`     // The url path for the caller
    HTTPMethod                      string                        `json:"httpMethod"`
    Headers                         map[string]string             `json:"headers"`
    MultiValueHeaders               map[string][]string           `json:"multiValueHeaders"`
    QueryStringParameters           map[string]string             `json:"queryStringParameters"`
    MultiValueQueryStringParameters map[string][]string           `json:"multiValueQueryStringParameters"`
    PathParameters                  map[string]string             `json:"pathParameters"`
    StageVariables                  map[string]string             `json:"stageVariables"`
    RequestContext                  APIGatewayProxyRequestContext `json:"requestContext"`
    Body                            string                        `json:"body"`
    IsBase64Encoded                 bool                          `json:"isBase64Encoded,omitempty"`
}

所以你可以看到,你提供给Golang AWS lambda处理程序的json映射只匹配一个键Body。这就是为什么printf只打印Testing Again的原因。

解决方案:

为了使用golang编写lambda获得正确的结果,我认为你可以参考 AWS DOC的这部分。(这对我们理解AWS API Gateway映射模板的工作方式非常有帮助。)

重写映射模板以匹配APIGatewayProxyRequest JSON标记。


感谢 @Sky.Li 指出问题的原因并进行了很好的解释。我没有找到与 APIGatewayProxyRequest 匹配的模板。所以,我使用 Lambda代理集成 将整个请求体传递给 Lambda 并在 Lambda 中处理它。 - Rahul Satal
不确定为什么AWS的{开发人员,SAM库}不能将这种疯狂抽象化,并让我们只使用标准的(w http.ResponseWriter,r *http.Request)接口! - hendry

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接