HTTP请求主体无法通过AWS API网关进入AWS lambda功能



我有一个非常基本的lambda函数,该函数用Scala部署到AWS lambda。当我通过AWS lambda控制台测试时,该功能正常工作。

这是用于调试目的的额外记录的功能。

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

我担心POJO输入/输出是Scala Bean可能正在引起问题,因此我暂时实施了Java版本,只是为了排除该版本。

AWS API网关上的集成请求默认设置为启用Lambda代理集成的资源。请注意,在此配置中,当我从AWS API Gateway Console测试数据时,数据已转换并进入,但并未将其一直到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 and do not 将其设置为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方法帖子对Postman的AWS API URL进行真实测试时,我会以Null为Null作为约会ID,我可以在CloudWatch日志中看到约会ID ID未设置在输入约会对象上。

我觉得我在这里缺少一些基本的东西。任何帮助将不胜感激。

可以在此处找到源代码

update

通过切换lambda处理程序功能以使用流而不是试图序列化/对json的序列化,从而解决了此问题。当使用API Gateway Lambda代理时,处理程序的输入是一个复杂的JSON结构,我不想尝试复制为Java/Scala类。将输入作为流进行处理,将其解析为jsonobject更容易,然后使用GSON或等效库将消息正文转换为我的POJO。下面的示例处理程序,您还可以在此处查看一个较大的示例

class CancellationHandler {
  def cancelAppointment(request: InputStream, response: OutputStream, context: Context): Unit = {
    val logger = context.getLogger
    val parser: JsonParser = new JsonParser
    var inputObj: JsonObject = null
    val gson: Gson = new Gson
    try {
      inputObj = parser.parse(IOUtils.toString(request, "UTF-8")).getAsJsonObject
    } catch {
      case e: IOException =>
        logger.log("Error while reading requestn" + e.getMessage)
        throw new RuntimeException(e.getMessage)
    }
    val body: String = inputObj.get("body").getAsString
    val appointment: Appointment = gson.fromJson(body, classOf[Appointment])
    val apiGatewayProxyResponse = new ApiGatewayProxyResponse
    val cancelResponse = new CancelResponse
    cancelResponse.setMessage("Cancelled appointment with id " + appointment.getAppointmentId)
    apiGatewayProxyResponse.setBody(gson.toJson(cancelResponse))
    apiGatewayProxyResponse.setStatusCode("200")
    val headerValues = new util.HashMap[String, String]
    headerValues put("Content-Type", "application/json")
    apiGatewayProxyResponse.setHeaders(headerValues)
    val output: String = gson.toJson(apiGatewayProxyResponse)
    IOUtils.write(output, response, "UTF-8")
  }
}

lambda代理的输入形状与常规非proxy 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
}

文档:http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-create-create-api-api-as-simple-proxy-for-lambda.html

相关内容

  • 没有找到相关文章

最新更新