Estoy tratando de configurar un ejemplo de hola mundo con AWS lambda y servirlo a través de la puerta de enlace api. Hice clic en "Crear una función Lambda", que configuró la API Gatway y seleccioné la opción Función en blanco. Agregué la función lambda que se encuentra en la guía de introducción al gateway de AWS :
exports.handler = function(event, context, callback) {
callback(null, {"Hello":"World"}); // SUCCESS with message
};
El problema es que cuando le hago una solicitud GET, devuelve una respuesta 502 { "message": "Internal server error" }
. Y los registros dicen "Error de ejecución debido a un error de configuración: respuesta de proxy Lambda mal formada".
Si se utiliza lambda como proxy, el formato de respuesta debe ser
{ "isBase64Encoded": true|false, "statusCode": httpStatusCode, "headers": { "headerName": "headerValue", ... }, "body": "..." }
Nota: el cuerpo debe estar encordado
fuente
callback(null,response);
statusCode
se requiere para que una llamada desde API Gateway tenga éxito.Sí, entonces creo que esto se debe a que en realidad no está devolviendo una respuesta http adecuada, por lo que recibe el error.
personalmente uso un conjunto de funciones como esta:
module.exports = { success: (result) => { return { statusCode: 200, headers: { "Access-Control-Allow-Origin" : "*", // Required for CORS support to work "Access-Control-Allow-Credentials" : true // Required for cookies, authorization headers with HTTPS }, body: JSON.stringify(result), } }, internalServerError: (msg) => { return { statusCode: 500, headers: { "Access-Control-Allow-Origin" : "*", // Required for CORS support to work "Access-Control-Allow-Credentials" : true // Required for cookies, authorization headers with HTTPS }, body: JSON.stringify({ statusCode: 500, error: 'Internal Server Error', internalError: JSON.stringify(msg), }), } } } // add more responses here.
Entonces simplemente haces:
var responder = require('responder') // some code callback(null, responder.success({ message: 'hello world'}))
fuente
De los documentos de AWS
fuente
Para Python3:
import json def lambda_handler(event, context): return { 'statusCode': 200, 'headers': { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' }, 'body': json.dumps({ 'success': True }), "isBase64Encoded": False }
Tenga en
body
cuenta que no es necesario configurarlo, solo puede estar vacío:'body': ''
fuente
Un caso muy muy especial, si pasa los encabezados directamente, existe la posibilidad de que tenga este encabezado:
"set-cookie": [ "........" ]
Pero Amazon necesita esto:
"set-cookie": "[ \\"........\\" ]"
fuente
Para cualquier otra persona que tenga problemas cuando la respuesta parezca válida. Esto no funciona:
callback(null,JSON.stringify( { isBase64Encoded: false, statusCode: 200, headers: { 'headerName': 'headerValue' }, body: 'hello world' })
pero esto hace:
callback(null,JSON.stringify( { 'isBase64Encoded': false, 'statusCode': 200, 'headers': { 'headerName': 'headerValue' }, 'body': 'hello world' })
Además, parece que no se permite que haya claves adicionales en el objeto de respuesta.
fuente
Si está usando Go con https://github.com/aws/aws-lambda-go , debe usar
events.APIGatewayProxyResponse
.func hello(ctx context.Context, event ImageEditorEvent) (events.APIGatewayProxyResponse, error) { return events.APIGatewayProxyResponse{ IsBase64Encoded: false, StatusCode: 200, Headers: headers, Body: body, }, nil }
fuente
He intentado todas las sugerencias anteriores, pero no funciona mientras el
body
valor no lo esString
return { statusCode: 200, headers: { "Content-Type": "application/json", "Access-Control-Allow-Origin": "*" }, body: JSON.stringify({ success: true }), isBase64Encoded: false };
fuente
Solo un fragmento de código para .net core y C # :
using Amazon.Lambda.APIGatewayEvents; ... var response = new APIGatewayProxyResponse { StatusCode = (int)HttpStatusCode.OK, Body = JsonConvert.SerializeObject(new { msg = "Welcome to Belarus! :)" }), Headers = new Dictionary<string, string> { { "Content-Type", "application/json" } } }; return response;
La respuesta de lambda será:
{"statusCode":200,"headers":{"Content-Type":"application/json"},"multiValueHeaders":null,"body":"{\"msg\":\"Welcome to Belarus! :)\"}","isBase64Encoded":false}
La respuesta de la puerta de enlace de la API será:
{"msg":"Welcome to Belarus! :)"}
fuente
Tuve este error porque eliminé accidentalmente la variable ServerlessExpressLambdaFunctionName del recurso CloudFormation AWS :: Serverless :: Api. El contexto aquí es https://github.com/awslabs/aws-serverless-express "Ejecute aplicaciones sin servidor y API REST utilizando su marco de aplicación Node.js existente, además de AWS Lambda y Amazon API Gateway"
fuente
En caso de que lo anterior no funcione para nadie, encontré este error a pesar de configurar la variable de respuesta correctamente.
Estaba haciendo una llamada a una base de datos RDS en mi función. Resultó que lo que estaba causando el problema eran las reglas del grupo de seguridad (de entrada) en esa base de datos.
Probablemente desee restringir las direcciones IP que pueden acceder a la API, pero si desea que funcione rápido / sucio para probar si ese cambio lo soluciona, puede configurarlo para que acepte todo así (también puede configurar el rango en los puertos para aceptar todos los puertos también, pero no hice eso en este ejemplo):
fuente
Una causa común del error "Respuesta de proxy Lambda con formato incorrecto" es
headers
que no{String: String, ...}
son pares clave / valor.Desde
set-cookie
las cabeceras pueden y deben aparecer en múltiplos, que están representados en http.request.callback.response como laset-cookie
llave que tiene unaArray
deStrings
valor en lugar de una solaString
. Si bien esto funciona para los desarrolladores, AWS API Gateway no lo entiende y genera un error de "Respuesta de proxy Lambda mal formada".Mi solución es hacer algo como esto:
function createHeaders(headers) { const singleValueHeaders = {} const multiValueHeaders = {} Object.entries(headers).forEach(([key, value]) => { const targetHeaders = Array.isArray(value) ? multiValueHeaders : singleValueHeaders Object.assign(targetHeaders, { [key]: value }) }) return { headers: singleValueHeaders, multiValueHeaders, } } var output = { ...{ "statusCode": response.statusCode, "body": responseString }, ...createHeaders(response.headers) }
Tenga en cuenta que lo
...
anterior no significa Yada Yada Yada . Es el operador de propagación ES6 .fuente
Aquí hay otro enfoque. Configure la plantilla de asignación en su solicitud y respuesta de integración de puerta de enlace API. Vaya a IntegrationRequest -> MappingTemplate -> seleccione "Cuando no hay plantillas definidas" -> escriba application / json para content-type. Entonces no tiene que enviar explícitamente un json. Incluso la respuesta que recibe de su cliente puede ser una cadena simple.
fuente
El formato de la respuesta de su función es la fuente de este error. Para que API Gateway maneje la respuesta de una función Lambda, la respuesta debe ser JSON en este formato:
{"isBase64Encoded": true | false, "statusCode": httpStatusCode, "headers": {"headerName": "headerValue", ...}, "body": "..."}
Aquí hay una función de ejemplo en Node.js con la respuesta formateada correctamente:
export.handler = (evento, contexto, devolución de llamada) => {
var responseBody = { "key3": "value3", "key2": "value2", "key1": "value1" }; var response = { "statusCode": 200, "headers": { "my_header": "my_value" }, "body": JSON.stringify(responseBody), "isBase64Encoded": false }; callback(null, response);
};
Ref: https://aws.amazon.com/premiumsupport/knowledge-center/malformed-502-api-gateway/
fuente
Python 3.7
antes de
{ "isBase64Encoded": False, "statusCode": response.status_code, "headers": { "Content-Type": "application/json", }, "body": response.json() }
Después
{ "isBase64Encoded": False, "statusCode": response.status_code, "headers": { "Content-Type": "application/json", }, "body": str(response.json()) //body must be of string type }
fuente
Si es nuevo en AWS y solo quiere que su URL funcione,
Si no ha creado un disparador para su función Lambda, navegue hasta la función en la aplicación Lambda Functions y cree un disparador eligiendo API Gateway.
Vaya a la aplicación API Gateway -> Elija su puerta de enlace de API de Lambda particular (ejecución de método) -> Haga clic en Solicitud de INTEGRACIÓN -> Desmarque "Usar integración de proxy de Lambda" (casilla de verificación).
Luego haga clic en " <-Método de ejecución " y haga clic en la sección Probar cliente. Proporcione las opciones y haga clic en el botón de prueba. Debería ver una respuesta de éxito.
Si aún no puede obtener una respuesta satisfactoria, cree un alias para la versión correcta (si tiene varias versiones en la función Lambda)
Elija la URL de los registros y use su herramienta POST / GET (Postman) y elija la autenticación como AWS Signature; proporcione sus claves de autenticación (AccessKey y SecretKey) en la solicitud del cartero con AWS Region & Service Name como lambda.
PD: Esto solo puede ayudar a los principiantes y puede ser irrelevante para otros.
fuente