Amazon web services HTTP请求主体无法通过AWS API网关访问AWS lambda函数
我有一个用Scala编写的非常基本的lambda函数,部署到AWS lambda。当我通过AWS Lambda控制台进行测试时,该功能运行良好 下面是为调试目的添加了一些附加日志的函数Amazon web services HTTP请求主体无法通过AWS API网关访问AWS lambda函数,amazon-web-services,aws-lambda,aws-api-gateway,Amazon Web Services,Aws Lambda,Aws Api Gateway,我有一个用Scala编写的非常基本的lambda函数,部署到AWS lambda。当我通过AWS Lambda控制台进行测试时,该功能运行良好 下面是为调试目的添加了一些附加日志的函数 package com.spacecorpshandbook.ostium.lambda.handler import java.util import com.google.gson.Gson import temp.{ApiGatewayProxyResponse, Appointment, Cancel
package com.spacecorpshandbook.ostium.lambda.handler
import java.util
import com.google.gson.Gson
import temp.{ApiGatewayProxyResponse, Appointment, CancelResponse}
/**
* Amazon Lambda handler adapter for the Cancellation application
*/
class CancellationHandler {
def cancelAppointment(appointment: Appointment): ApiGatewayProxyResponse = {
System.out.println("++++ appointmentId is: " + appointment.getAppointmentId)
val apiGatewayProxyResponse = new ApiGatewayProxyResponse
val cancelResponse = new CancelResponse
cancelResponse.setMessage("Cancelled appointment with id " + appointment.getAppointmentId)
val gson: Gson = new Gson
apiGatewayProxyResponse.setBody(gson.toJson(cancelResponse))
apiGatewayProxyResponse.setStatusCode("200")
val headerValues = new util.HashMap[String, String]
headerValues put("Content-Type", "application/json")
apiGatewayProxyResponse.setHeaders(headerValues)
System.out.println("+++++ message before returning: " + apiGatewayProxyResponse.getBody)
apiGatewayProxyResponse
}
}
我担心作为Scala bean的POJO输入/输出可能会引起问题,所以我临时实现了Java版本,只是为了排除这种可能性
AWS API网关上的集成请求默认设置为启用Lambda代理集成的任意资源。注意,在这个配置中,当我从AWS API网关控制台进行测试时,数据会被转换并进入,但不会一直到达lambda函数
Execution log for request test-request
Fri Dec 09 11:14:40 UTC 2016 : Starting execution for request: test-invoke-request
Fri Dec 09 11:14:40 UTC 2016 : HTTP Method: PUT, Resource Path: /cancel-appointment
Fri Dec 09 11:14:40 UTC 2016 : Method request path: {}
Fri Dec 09 11:14:40 UTC 2016 : Method request query string: {}
Fri Dec 09 11:14:40 UTC 2016 : Method request headers: {Content-Type= application/json}
Fri Dec 09 11:14:40 UTC 2016 : Method request body before transformations: {
"applicationId": "asdfsfa"
}
Fri Dec 09 11:14:40 UTC 2016 : Endpoint request headers: {x-amzn-lambda-integration-tag=test-request, Authorization=****************************************************************************************************************************************************************************************************************************************************************************************************************************************5c044d, X-Amz-Date=20161209T111440Z, x-amzn-apigateway-api-id=l5tcmj0vlk, Accept=application/json, User-Agent=AmazonAPIGateway_l5tcmj0vlk, Host=lambda.us-east-1.amazonaws.com, X-Amz-Content-Sha256=857a062940a7fbb8134bad1c007e9975a10bd8323c39f6040e797a98e87ea1f6, X-Amzn-Trace-Id=Root=1-584a9220-9cd537954952cca7daee32bf, Content-Type=application/json}
Fri Dec 09 11:14:40 UTC 2016 : Endpoint request body after transformations: {"resource":"/cancel-appointment","path":"/cancel-appointment","httpMethod":"PUT","headers":{"Content-Type":" application/json"},"queryStringParameters":null,"pathParameters":null,"stageVariables":null,"requestContext":{"accountId":"456204981758","resourceId":"xznq3u","stage":"test-invoke-stage","requestId":"test-invoke-request","identity":{"cognitoIdentityPoolId":null,"accountId":"456204981758","cognitoIdentityId":null,"caller":"456204981758","apiKey":"test-invoke-api-key","sourceIp":"test-invoke-source-ip","accessKey":"ASIAJ5D7KU524H7CTTTQ","cognitoAuthenticationType":null,"cognitoAuthenticationProvider":null,"userArn":"arn:aws:iam::456204981758:root","userAgent":"Apache-HttpClient/4.5.x (Java/1.8.0_102)","user":"456204981758"},"resourcePath":"/cancel-appointment","httpMethod":"PUT","apiId":"l5tcmj0vlk"},"body":"{\n \"applicationId\": \"asdfsfa\"\n}","isBase64Encoded":false}
Fri Dec 09 11:14:40 UTC 2016 : Endpoint response body before transformations: {"statusCode":"200","headers":{"Content-Type":"application/json"},"body":"{\"message\":\"Cancelled appointment with id null\"}"}
Fri Dec 09 11:14:40 UTC 2016 : Endpoint response headers: {x-amzn-Remapped-Content-Length=0, x-amzn-RequestId=adcadf25-be00-11e6-8855-75e96d772946, Connection=keep-alive, Content-Length=128, Date=Fri, 09 Dec 2016 11:14:39 GMT, Content-Type=application/json}
Fri Dec 09 11:14:40 UTC 2016 : Method response body after transformations: {"message":"Cancelled appointment with id null"}
Fri Dec 09 11:14:40 UTC 2016 : Method response headers: {Content-Type=application/json, X-Amzn-Trace-Id=Root=1-584a9220-9cd537954952cca7daee32bf}
Fri Dec 09 11:14:40 UTC 2016 : Successfully completed execution
Fri Dec 09 11:14:40 UTC 2016 : Method completed with status: 200
如果我添加了一个特定的方法,比如POST和donot将其设置为Lambda代理集成,那么我确实看到了提供请求主体数据将其添加到Lambda函数中,正确地反序列化到我的POJO中并返回的结果
Execution log for request test-request
Fri Dec 09 11:22:02 UTC 2016 : Starting execution for request: test-invoke-request
Fri Dec 09 11:22:02 UTC 2016 : HTTP Method: POST, Resource Path: /cancel-appointment
Fri Dec 09 11:22:02 UTC 2016 : Method request path: {}
Fri Dec 09 11:22:02 UTC 2016 : Method request query string: {}
Fri Dec 09 11:22:02 UTC 2016 : Method request headers: {}
Fri Dec 09 11:22:02 UTC 2016 : Method request body before transformations: {
"appointmentId" : "sfssdf"
}
Fri Dec 09 11:22:02 UTC 2016 : Endpoint request headers: {x-amzn-lambda-integration-tag=test-request, Authorization=****************************************************************************************************************************************************************************************************************************************************************************************************************************************a8dc41, X-Amz-Date=20161209T112202Z, x-amzn-apigateway-api-id=l5tcmj0vlk, Accept=application/json, User-Agent=AmazonAPIGateway_l5tcmj0vlk, Host=lambda.us-east-1.amazonaws.com, X-Amz-Content-Sha256=875dad4d4e05f8c12a7ca8aeaf69046d4153fc7f910e1eff1959cb011e8313a0, X-Amzn-Trace-Id=Root=1-584a93da-f841704d9feb371b31e41cb9, Content-Type=application/json}
Fri Dec 09 11:22:02 UTC 2016 : Endpoint request body after transformations: {
"appointmentId" : "sfssdf"
}
Fri Dec 09 11:22:02 UTC 2016 : Endpoint response body before transformations: {"statusCode":"200","headers":{"Content-Type":"application/json"},"body":"{\"message\":\"Cancelled appointment with id sfssdf\"}"}
Fri Dec 09 11:22:02 UTC 2016 : Endpoint response headers: {x-amzn-Remapped-Content-Length=0, x-amzn-RequestId=b4f5efce-be01-11e6-91c3-5b1e06f831e2, Connection=keep-alive, Content-Length=130, Date=Fri, 09 Dec 2016 11:22:02 GMT, Content-Type=application/json}
Fri Dec 09 11:22:02 UTC 2016 : Method response body after transformations: {"statusCode":"200","headers":{"Content-Type":"application/json"},"body":"{\"message\":\"Cancelled appointment with id sfssdf\"}"}
Fri Dec 09 11:22:02 UTC 2016 : Method response headers: {X-Amzn-Trace-Id=Root=1-584a93da-f841704d9feb371b31e41cb9, Content-Type=application/json}
Fri Dec 09 11:22:02 UTC 2016 : Successfully completed execution
Fri Dec 09 11:22:02 UTC 2016 : Method completed with status: 200
所以现在一切看起来都很好,但是当我使用HTTP方法POST对PostMan提供的AWS API URL进行实际测试时,我得到了以null作为约会Id的响应,我可以在CloudWatch日志中看到,在输入约会对象上没有设置约会Id
我觉得我错过了一些基本的东西。任何帮助都将不胜感激
可以找到源代码
更新
通过将lambda处理程序函数切换为使用Stream,而不是尝试将JSON序列化/反序列化为POJO,解决了此问题。使用API网关Lambda代理时,处理程序的输入是一个复杂的JSON结构,我不想尝试将其复制为Java/Scala类。将输入作为流进行处理,将其解析为JsonObject,然后使用Gson或等效库将消息体转换为my POJO更容易。在下面的示例处理程序中,您还可以看到一个更大的示例
Lambda代理的输入形状将不同于常规非代理Lambda集成的形状。当然,这对于您的用例很重要,因为您使用的是Java/Scala,其中必须显式地构造输入POJO 以下是代理输入的外观:
{
"resource": "\/pets",
"path": "\/pets",
"httpMethod": "POST",
"headers": null,
"queryStringParameters": null,
"pathParameters": null,
"stageVariables": null,
"requestContext": {
...
"stage": "test-invoke-stage",
"requestId": "test-invoke-request",
"identity": {
...
},
"resourcePath": "\/pets",
"httpMethod": "POST"
},
"body": "{\n \"foo\":\"bar\"\n}", <---- here's what you're looking for
"isBase64Encoded": false
}
{
“资源”:“\/pets”,
“路径”:“\/pets”,
“httpMethod”:“POST”,
“标题”:空,
“queryStringParameters”:空,
“路径参数”:null,
“阶段变量”:空,
“请求上下文”:{
...
“阶段”:“测试调用阶段”,
“请求ID”:“测试调用请求”,
“身份”:{
...
},
“资源路径”:“\/pets”,
“httpMethod”:“POST”
},
“body”:“{\n\“foo\”:“bar\”\n}”,谢谢。我现在正在玩这个,我想我需要将我的处理程序转换为使用streams,这样我就可以更轻松地将输入处理为JSON。这无疑将我推向了正确的方向。当我找到一个可行的解决方案时,我会更新这篇文章。
{
"resource": "\/pets",
"path": "\/pets",
"httpMethod": "POST",
"headers": null,
"queryStringParameters": null,
"pathParameters": null,
"stageVariables": null,
"requestContext": {
...
"stage": "test-invoke-stage",
"requestId": "test-invoke-request",
"identity": {
...
},
"resourcePath": "\/pets",
"httpMethod": "POST"
},
"body": "{\n \"foo\":\"bar\"\n}", <---- here's what you're looking for
"isBase64Encoded": false
}