HTTP request issue Internal Server error - node.js

I am having issues with an HTTP response giving me a status code: 502, and error message: Internal Server Error. My setup is an AWS Lambda written in NodeJS making an HTTPS POST request to an AWS API Gateway integrated with another Lambda, as its backend.
The strange part is the Lambda acting as the backend of the API receives all the POST requests just fine and is able to execute its functions perfectly, but its callback responds to the other Lambda with an error.
Below is the callback on the lambda on the API Gateway side
const done = (err, res) => callback(err, {
statusCode: err ? JSON.stringify(err.code) : '200',
body: err ? JSON.stringify(err.message) : JSON.stringify(res),
headers: {
'Content-Type': 'application/json',
}
});
And here is the code from the other lambda making an https POST request
const req = https.request(options, (res) => {
console.log('statusCode:', res.statusCode);
console.log('headers:', res.headers);
res.on('data', (d) => {
process.stdout.write(d);
});
res.on('end', function () {
console.log(JSON.stringify(body));
});
});
req.on('error', (e) => {
console.error(e);
console.log("request error");
});
req.write(JSON.stringify(payload));
console.log("req.end");
req.end();
I feel the problem is in these blocks of code because if I change the callback of the Lambda integrated API Gateway to hardcode the response to a 200 status code, then everything works fine.

Problem I see with your code is, if err.code is empty or invalid value, then you will get 502 on API Gateway. You need to fix the code so that it sends back a valid http response with a valid status code.
If your status code is invalid or empty then it will throw a 502 to the caller since the http response from lambda is invalid.
Hope it helps.

Problem is fixed now. No code changes were necessary but the problem was that the Lambda's Node.Js source files on the API Gateway side needed to be zipped with the necessary dependencies or node_modules as explained here http://docs.aws.amazon.com/lambda/latest/dg/nodejs-create-deployment-pkg.html

I was facing a similar problem of getting Internal server error while calling external API from lambda function.
Earlier time out for lambda function was 6sec and I increased to some 25sec. After that everything works fine.
Nodejs is asynchronous before getting API response next lines were executing irrespective of using async await.

Related

NodeJS http-proxy error response.end() not working

Here's the code:
proxy.web(
req,
res,
{ changeOrigin: false, target: 'http://' + gotDomain.ip + ':' + gotDomain.port },
function (error, req, res) => {
console.log('Error')
res.end('Error')
}
)
If I stop the target server, the console log fires.
The response res.end('Error') does not work.
The request just hangs on the client side. I can run any code I want in the error callback and I can see the res variable is an http response object. I've tried adding:
res.writeHead(500, {
'Content-Type': 'text/plain'
});
I've tried using the proxy.on('error'... setup and the results are exactly the same:
The callback runs
The res variable is a valid http response object
Whatever I put in res.end() doesn't get sent to the client
The client hangs forever waiting for a response.
I've checked this answer:
Node.js http-proxy: Error response not sent to client
I'm not sure how that solution could work because my proxy response doesn't have status() or send() methods. I get TypeError: res.status is not a function if I try those.
With http-proxy, I use end() whenever I'm returning a response.

How to asynchronously make HTTP Requests in AWS Lambda Node.js runtime

I have created an API endpoint that returns an integer when it is successfully accessed with an HTTP Post request. I want an AWS CloudWatch scheduled process to run an AWS Lambda function every minute to check the API endpoint so make sure the value is not zero. I have set up the scheduled AWS CloudWatch process and the AWS Lambda function, where the runtime is Node.js 10. However, when I look at the AWS CloudWatch group's stream log, the logs seem to be out of order. I suspect this is because of the HTTP Request to the API endpoint is running asynchronously, but I ultimately do not know. The time that it takes to log the value of this HTTP Request to the API end point seems to be much longer than the actual time to process the request.
Here is the Node.js lambda function that is being run on a minutely basis:
exports.handler = async (event) => {
var datetime = new Date();
var request = require("request");
var options = {
method: 'POST',
url: 'https://website.com/api/getDataPoints',
headers:
{
'cache-control': 'no-cache',
'content-type': 'text/plain'
},
body: '{"token" : "yT7g8urUFmEZwQrJNHgQGRDA9zScpNzPM3rb"}'
};
await request(options, function (error, response, body) {
if (error)
{
throw new Error(error);
// Email and SMS message that this is having an error
}
if (body == 0)
{
// Email and SMS message that this is having an error
// Restart EC2 server
}
console.log(datetime.toString() + " - " + body + " Data Points!");
});
};
Here is the AWS CloudWatch log, where it's easier to see the delay in logging the response from the HTTP Request:
Any insight into the cause of this perceived log delay or suggestions on how to achieve similar results in a more efficient way would be greatly appreciated! Thank you!
Here is what is happening: the await is returning immediately because the request function does not return a promise, so the callback is happening after the lambda function exits. The reason why there is such a long delay in seeing the log is that when your lambda function becomes idle (meaning all handler functions have returned, even if there are callbacks waiting) AWS can suspend any executing code until a new invocation of the function. So in your case when the next minute rolls around and the lambda function is invoked again, AWS will un-suspend any executing code and the callback kicks off immediately and you see the log for the previous invocation.
To solve this you want to make sure the handler function doesn't return until all work has been completed (which is what I think you were intending to do with the await). So wrap the request call in a function that returns a promise which is resolved in the callback and use await on the wrapper function.
function doRequest() {
return new Promise((resolve, reject) => {
request(options, function (error, response, body) {
if (error){
throw new Error(error);
// Email and SMS message that this is having an error
}
if (body == 0){
// Email and SMS message that this is having an error
// Restart EC2 server
}
console.log(datetime.toString() + " - " + body + " Data Points!");
resolve();
});
});
}
await doRequest();

Will AWS Lambda wait for my response?

I'm using AWS lambda as SQS listener in my project. Some time no response got in my log, most of the time it's working.
code
console.log('Befor Req ' + post_data);
// Set up the request
var post_req = http.request(post_options, function(res) {
res.setEncoding('utf8');
res.on('data', function (response) {
console.log('Request data' + post_data);
console.log('Response ' + response);
});
res.on('error', function (err) {
console.log(err);
})
});
// post the data
post_req.write(post_data);
post_req.end();
Here I got all fine in before request, sometimes the log inside the request not get logging.
I check the other side request and response are logged and all fine.
Is this any specific issue with AWS LAMBDA?
The log inside the request is an asynchronous callback's either log inside your on success or your failure callback should prints.
If not There are two posibilities.
one is you are terminating lambda before that async code completed
posibility no 2 is, your lambda got timesout before that async request completed . see this scenario may works on sometime and fails on other time. It depends on our async execution time and lambda timeout
TO ensure this check your cloudwatch log for lines task timedout after x second. And you will be get 502 on that time if you are using lambda proxy in API gateway. see below

Malformed Lambda proxy response

I am trying to access a Lambda function using a POST method. When I try to test the POST resource I put in the Request body {"article_url": "http://technewstt.com/bd1108/"}
This makes the API Gateway respond with Execution failed due to configuration error: Malformed Lambda proxy response My code is below.
exports.handler = (event, context, callback) => {
//event = {"article_url": "http://technewstt.com/bd1108/"};
console.log(event.article_url);
var http = require('http');
var TextAPI = require('textapi');
var textapi = new TextAPI({
application_id: "randomn numbers",
application_key: "randomn numbers"
});
textapi.summarize({
url: event.article_url,
sentences_number: 3
}, function(error, response) {
if (error === null) {
response.sentences.forEach(function(s) {
console.log(s);
//var body = JSON.parse(s);
// TODO implement
//callback(null, s);
callback(null, {"statusCode": 200, "body": JSON.stringify(s)});
});
}
});
};
Please note that if I uncomment the second line the API gateway works fine.
Any help with this issue would be greatly appreciated.
You are using Lambda Proxy integration which always expects output of the format http://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-output-format
"Malformed Lambda proxy response" is returned if the lambda response format is unexpected. You can enable logging with full request/responses which should show you the response being returned from lambda. Its likely there was an error in you lambda function which returned an error.

How to send http request with nodejs AWS Lambda?

I'm using AWS Lambda to drive an Alexa Skill Kit development. In an attempt to track events, I'd like the script to send an HTTP request on launch, however from the cloud logs it appears as though the http.get function is being skipped during the execution process.
The code is shown below (google.com replaces the analytics tracking url - which has been tested in the browser);
exports.handler = function (event, context) {
var skill = new WiseGuySkill();
var http = require('http');
var url = 'http://www.google.com';
console.log('start request to ' + url)
http.get(url, function(res) {
console.log("Got response: " + res.statusCode);
// context.succeed();
}).on('error', function(e) {
console.log("Got error: " + e.message);
// context.done(null, 'FAILURE');
});
console.log('end request to ' + url);
skill.execute(event, context);
};
The context objects have been commented out to allow for 'skill.execute' to function, yet either way this HTTP request is not executing. Only the 'start' and 'end' console.logs are recorded, those internal in the function do not.
Is this a async issue? Thanks.
You need to make sure the handler is being triggered. There are two ways of accomplishing this:
You could set up a new API endpoint and execute a request on that.
You could hit the Test button and your function would be invoked with the given data.
I copied and pasted your whole snippet except for the first and the last lines (because I don't have customSkill defined anywhere). I was able to get a 200 response code.
In order to successfully complete the http request, the http.get function must be incorporated into a callback function. Else the process will not be completed and will end prematurely, using a callback allows the http request to complete (with or without an error) before continuing with the rest of the function.
WiseGuySkill.prototype.eventHandlers.onLaunch = function (launchRequest, session, response) {
// Call requestFunction to make the http.get call.
// Get response from requestFunction using requestCallback
requestFunction(function requestCallback(err) {
// If error occurs during http.get request - respond with console.log
if (err) {
console.log('HTTP Error: request not sent');
}
ContinueIntent(session,response);
});
};
The function 'requestFunction' calls http.get and fires the callback.
function requestFunction(requestCallback){
var url = "http://www.google.com";
http.get(url, function(res) {
console.log("Got response: " + res.statusCode);
requestCallback(null);
}).on('error', function (e) {
console.log("Got error: ", e);
});
}
And obviously ensure you have required 'http' at the start of the script.
Hope this helps anybody else new to this!

Resources