Why is this HTTP request not working on AWS Lambda?
Of course, I was misunderstanding the problem. As AWS themselves put it:
For those encountering nodejs for the first time in Lambda, a common error is forgetting that callbacks execute asynchronously and calling
context.done()
in the original handler when you really meant to wait for another callback (such as an S3.PUT operation) to complete, forcing the function to terminate with its work incomplete.
I was calling context.done
way before any callbacks for the request fired, causing the termination of my function ahead of time.
The working code is this:
var http = require('http');
exports.handler = function(event, context) {
console.log('start request to ' + event.url)
http.get(event.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 ' + event.url);
}
Update: starting 2017 AWS has deprecated the old Nodejs 0.10 and only the newer 4.3 run-time is now available (old functions should be updated). This runtime introduced some changes to the handler function. The new handler has now 3 parameters.
function(event, context, callback)
Although you will still find the succeed
, done
and fail
on the context parameter, AWS suggest to use the callback
function instead or null
is returned by default.
callback(new Error('failure')) // to return error
callback(null, 'success msg') // to return ok
Complete documentation can be found at http://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-handler.html
I faced this issue on Node 10.X version. below is my working code.
const https = require('https');
exports.handler = (event,context,callback) => {
let body='';
let jsonObject = JSON.stringify(event);
// the post options
var optionspost = {
host: 'example.com',
path: '/api/mypath',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'blah blah',
}
};
let reqPost = https.request(optionspost, function(res) {
console.log("statusCode: ", res.statusCode);
res.on('data', function (chunk) {
body += chunk;
});
res.on('end', function () {
console.log("Result", body.toString());
context.succeed("Sucess")
});
res.on('error', function () {
console.log("Result Error", body.toString());
context.done(null, 'FAILURE');
});
});
reqPost.write(jsonObject);
reqPost.end();
};
Simple Working Example of Http request using node.
const http = require('https')
exports.handler = async (event) => {
return httprequest().then((data) => {
const response = {
statusCode: 200,
body: JSON.stringify(data),
};
return response;
});
};
function httprequest() {
return new Promise((resolve, reject) => {
const options = {
host: 'jsonplaceholder.typicode.com',
path: '/todos',
port: 443,
method: 'GET'
};
const req = http.request(options, (res) => {
if (res.statusCode < 200 || res.statusCode >= 300) {
return reject(new Error('statusCode=' + res.statusCode));
}
var body = [];
res.on('data', function(chunk) {
body.push(chunk);
});
res.on('end', function() {
try {
body = JSON.parse(Buffer.concat(body).toString());
} catch(e) {
reject(e);
}
resolve(body);
});
});
req.on('error', (e) => {
reject(e.message);
});
// send the request
req.end();
});
}
Yeah, awendt answer is perfect. I'll just show my working code... I had the context.succeed('Blah'); line right after the reqPost.end(); line. Moving it to where I show below solved everything.
console.log('GW1');
var https = require('https');
exports.handler = function(event, context) {
var body='';
var jsonObject = JSON.stringify(event);
// the post options
var optionspost = {
host: 'the_host',
path: '/the_path',
method: 'POST',
headers: {
'Content-Type': 'application/json',
}
};
var reqPost = https.request(optionspost, function(res) {
console.log("statusCode: ", res.statusCode);
res.on('data', function (chunk) {
body += chunk;
});
context.succeed('Blah');
});
reqPost.write(jsonObject);
reqPost.end();
};