AWS lambda api gateway error “Malformed Lambda proxy response” - aws-lambda

My AWS ApiGateway invokes this lambda function :
const handler = (event, context) => {
const theResponse = {
"statusCode": 200,
"isBase64Encoded": false,
"headers": {
"Content-Type": "application/json"
},
"body": "hello, world"
};
switch (event.httpMethod) {
case 'GET':
theResponse["body"] = `method ${event.httpMethod} detected`;
break;
default:
theResponse["statusCode"] = 404;
theResponse["body"] = `Unsupported method ${event.httpMethod} detected`;
break;
}
return theResponse;
};
module.exports = {
handler,
};
Any thoughts to why this errors with :
{"message": "Internal server error"}
Received response. Status: 200, Integration latency: 344 ms
Endpoint response body before transformations: null
Execution failed due to configuration error: Malformed Lambda proxy response
Method completed with status: 502
I tried replacing return (theResponse); with return JSON.stringify(theResponse); but this also returns the same error.
However if I replace return theResponse; with return {"statusCode":200, "body":"hello, world"}; then the API executes without errors.
Looks to me like a lamda_proxy integration issue but I can't see why. thanks.

Bearrider!
I guess it is related to the way you are building your response object:
Try stringify only the body attribute:
case 'GET':
theResponse["body"] = JSON.stringify(`method ${event.httpMethod} detected`);
break;
default:
theResponse["statusCode"] = 404;
theResponse["body"] = JSON.stringify(`Unsupported method ${event.httpMethod} detected`);
break;
}

Related

Lambda#Edge function result failed validation

I have a lambda#edge in Viewer Request that is generating this error:
ERROR Validation error: Lambda function result failed validation, the function tried to add read-only header, headerName : Transfer-Enoding.
I tried to return this event in case of redirection:
const response = {
status: '301',
statusDescription: 'Found',
headers: {
'location': [{
key: 'location',
value: 'https://test.com'
}]
}
}
callback(null, response)
I also tried keeping the same event but I get the same error
const response = event.Records[0].cf.response;
response.status = 301;
response.statusDescription = 'Found';
response.headers['location'] = [{ key: 'Location', value:'https://www.test.com'}];
Cqn someone tells me how to fix this ?
PS: Even requests that pass by this lambda and doesnt verify the redirection condition result in this error also.

NodeJS: AWS SDK V3: Not receiving any response data from lambda function

I'm trying to use the v3 javascript sdk to invoke a AWS Lambda function, and I'm having problems getting any meaningful response.
My code looks like so...
const { Lambda } = require("#aws-sdk/client-lambda");
const client = new Lambda();
const params = {
FunctionName: "MyLamdaFuncton",
Payload: JSON.stringify({ "action": "do_something" }),
InvocationType: "Event"
};
client.invoke(params)
.then((response) => {
console.log(JSON.stringify(response,null,4));
})
.catch((err) => {
console.error(err);
})
I can confirm from checking the CloudWatch logs that the lambda function works as exepcted. However this is the response I get in my NodeJS code...
{
"$metadata": {
"httpStatusCode": 202,
"requestId": "d6ba189d-9156-4f01-bd51-efe34a66fe34",
"attempts": 1,
"totalRetryDelay": 0
},
"Payload": {}
}
How do I get the actual response and status from the Lambda function?
If I change the payload above to intentionally throw an exception in my Lambda, the response in the console is still exactly the same.
update:
The Lambda function is written in Ruby. The response is returned like so...
{ statusCode: 200, body: JSON.generate(response.success?) }
where "response" is from another service it calls internally.
I've figured out what I was doing wrong. The issue was the "InvocationType". I got it working by changing to...
InvocationType: "RequestResponse"
Then I had to extract the response data like so...
const response_data = JSON.parse(new TextDecoder("utf-8").decode(response.Payload))

Returning custom http status codes on AWS Lambda error

I'm working with an AWS Lambda with serverless framework and I want to return a custom http status code when an error occurs but I'm always getting a 502 status code when I call my endpoint with axios.
module.exports.handler = async (event, context, callback) => {
try {
// some stuff
} catch (err) {
// error here
let myErrorObj = {
errorType : "InternalServerError",
httpStatus : 500,
requestId : context.awsRequestId,
trace : {
"function": "abc()",
"line": 123,
"file": "abc.js"
},
body: err
}
callback(JSON.stringify(myErrorObj));
}
}
But the object I'm getting back contains the property status: 502 and data.message: "Internal server error"
Any ideas of what is going on here?
status code 502 indicates the lambda's response to API Gateway is in an incorrect format.
The correct response for an async function (if not integration method stated in serverless YAML file, it would use Lambda Proxy Integration):
export const dummyFunction = async (event, context, callback) =>
{
// ... logic
return {
statusCode: 500,
body: JSON.stringify({...data}),
}
};
Callback is only for non-async function only. Please refer to full documentation.
Are you using API Gateway with your Lambda? If so, what you are returning in the callback is incorrect. The object you return must match this format: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-output-format
So you can either just callback(err) and let AWS generate a 500 or if you want the added error context something like:
let myErrorObj = {
statusCode : 500,
body: JSON.stringify({
requestId : context.awsRequestId,
trace : {
"function": "abc()",
"line": 123,
"file": "abc.js"
}
error: err
}
})
}
callback(null, myErrorObj);
If you want requestId and trace attributes you would need to add them into the body.

API Gateway + Lambda - CORS Issue

i am experiencing continuing problems with the CORS integration for API Gateway + Lambda. i have enabled CORs for the resources associated with the API. Everything appears to work fine via Lambda testing, Postman testing etc, but calling the api from a webpage script is giving the following error "No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access. The response had HTTP status code 415." Do I need to change the Lambda function? Thanks
Here is my simple Lambda code..
'use strict';
var AWS = require('aws-sdk');
var dclient = new AWS.DynamoDB.DocumentClient();
var getItems = (event, context, callback) => {
var params = {
TableName: "OMSCaseDataTest",
Key: {
"IncidentID": event.IncidentID
}
}
dclient.get(params, (error, data) => {
if (error) {
callback(null, "error occured")
} else {
callback(null, data);
}
});
};
exports.getItems = getItems;
If you are using proxy integration in API Gateway, then enabling CORS from API Gateway doesn't work. You have to set the Header 'Access-Control-Allow-Origin' from your Lambda code itself.
Its mentioned in the doc.
Python code sample:
response = {
'statusCode': 200,
'headers': {
'Access-Control-Allow-Origin': '*'
},
'body': json.dumps({'message': 'CORS enabled')
}
return response
Assuming you're using proxy integration, you'll need to handle the CORS yourself. Your lambda function will need to handle the HTTP methods differently. CORS problems usually occur when the pre-flight option request is not entertained. Here's a code snippet could help your cause.
function main(event, context, lambdaCallback) {
if (event.httpMethod === 'OPTIONS') {
doneOptions(200, '{"status": "OK"}', 'application/json', lambdaCallback);
} else if (event.httpMethod === 'POST') {
// do your POST here
} else {
return done(400, '{"message":"Invalid HTTP Method"}', 'application/json', lambdaCallback);
}
}
The functions that return the HTTP 200 to your frontend which decide what your frontend/API could call and what's not.
function doneOptions(statusCode, body, contentType, lambdaCallback, isBase64Encoded = false) {
lambdaCallback(null, {
statusCode: statusCode,
isBase64Encoded: isBase64Encoded,
body: body,
headers: {
'Content-Type': contentType,
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': 'Authorization,Content-Type',
'Access-Control-Allow-Method': 'GET,POST,OPTIONS',
}
});
}
Some times the lambda time out causes CORS error. You can increase the timeout this may fix the issue.

custom authorizers in Amazon API Gateway 500 error

I use Serverless-Authentication-boilerplate and want to map custom error response. But it always return 500 error.
authorize.js
// Authorize
function authorize(event, callback) {
let providerConfig = config(event);
try {
let data = utils.readToken(event.authorizationToken, providerConfig.token_secret);
console.log("Decrypted data: " + JSON.stringify(data));
let methodArn = event.methodArn.replace(/(GET|POST|PUT|DELETE)/g, '*').replace(/mgnt.+/g, 'mgnt/*');
console.log(`Change methodArn to: ${methodArn}`);
// TODO: handle expiration time validation
callback(null, utils.generatePolicy(
data.id, // which is $context.authorizer.principalId
'Allow',
methodArn));
} catch (err) {
console.log(err);
callback('401 Unauthenticated');
}
}
s-function.json
responses:{
"401 Unauthenticated.*": {
"statusCode": "401"
},
"default": {
"statusCode": "200",
"responseModels": {
"application/json;charset=UTF-8": "Empty"
},
"responseTemplates": {
"application/json;charset=UTF-8": ""
}
}
}
After ask to Amazon Web Services.
Unfortunately the mapping of the Authorizer is not currently configurable and every returned error from a lambda function will map to a 500 status code in API gateway. Moreover, the mapping is performed on an exact string match of the output, so, in order to return the intended 401 Error to the client, you should execute a call to 'context.fail('Unauthorized');.
Finally, I change
callback('401 Unauthenticated');
to
context.fail('Unauthorized');
and work fine.
Sharing to whom may encounter this.

Resources