2016-12-09 5 views
0

У меня есть очень простая функция лямбда, написанная на Scala, развернутой в AWS Lambda. Функция отлично работает, когда я тестирую ее через консоль AWS Lambda.Тело запроса HTTP не доходит до функции лямбда AWS через шлюз API AWS

Вот функция с дополнительными регистрациями, добавленными для отладки.

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 бобы могли быть причиной проблем, так я реализовал Java версии временно просто исключаю.

Запрос интеграции на шлюзе AWS API устанавливается по умолчанию в качестве ресурсов ЛЮБОЙ с включенной поддержкой Lambda Proxy Integration. Обратите внимание, что в этой конфигурации, когда я испытываю от AWS API шлюза утешать данные преобразуются и идет в но does't сделать все это путь к лямбда-функции

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 и не не установить его в качестве лямбда-прокси Интеграция я действительно вижу, что обеспечивают запрос данных тела делает его к лямбда-функции, правильно десериализовать в мой 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 

так что все теперь выглядит здорово, однако, когда я действительно делаю настоящий тест против URL API AWS из PostMan, используя HTTP метод POST Я получаю ответ с нулевым значением в качестве идентификатора встречи, и я могу видеть в журналах CloudWatch, что назначение ID не было установлено на входном объекте Назначение.

Я чувствую, что мне не хватает чего-то основного здесь. Любая помощь будет принята с благодарностью.

исходный код может быть найден here

Update

эта проблема решена путем включения функции обработчика лямбда использовать поток, а не пытаться сериализации/десериализации JSON в POJOs. При использовании прокси-сервера Lambda API Gateway вход для обработчика представляет собой сложную структуру JSON, которую я не хотел пытаться реплицировать как класс Java/Scala. Легче обрабатывать входные данные в виде потока, анализировать его в JsonObject и затем преобразовывать тело сообщения в мой POJO, используя Gson или эквивалентную библиотеку. Пример обработчик ниже, вы можете также увидеть больший пример here

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 request\n" + 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") 
    } 

} 

ответ

0

Формой входа для прокси-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 
} 

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

+0

Спасибо. Я играю с этим сейчас, я думаю, мне нужно преобразовать обработчик для использования потоков, чтобы я мог легко обрабатывать входные данные как JSON. Это определенно подтолкнуло меня в правильном направлении. Я буду обновлять этот пост, когда я соглашусь на рабочее решение. – jrobison151

+0

Вам действительно не нужны потоки. Я делаю это проще, чем с потоками из примера AWS. У меня есть [код шаблона онлайн] (http://www.jsonschema2pojo.org/), чтобы показать вам, как это сделать. –

 Смежные вопросы

  • Нет связанных вопросов^_^