I am attempting to make a request to another API from a Lambda. I am finding that using the NodeJS http and https modules allow for GET requests but any others (e.g. POST) do not work; POST coincidentally is the only method I need to work for the service I am attempting to call.
Here is a working example of Lambda performing a GET and receiving a 200 response:
const https = require('https')
function handler(event, context, callback) {
const options = {
hostname: 'encrypted.google.com'
}
https
.get(options, (res) => {
console.log('statusCode:', res.statusCode);
res.on('end', callback.bind(null, null))
})
.on('error', callback);
}
exports.handler = handler
So that proves that he request is allowed. However, if the script attempts to make the same request using the .request() method of the https (or https) lib/module the request never finishes and the Lambda times out.
const https = require('https')
function handler(event, context, callback) {
const options = {
hostname: 'encrypted.google.com',
method: 'GET'
}
https
.request(options, (res) => {
console.log('statusCode:', res.statusCode);
res.on('end', callback.bind(null, null))
})
.on('error', callback);
}
exports.handler = handler
I don't know what I am doing wrong. The call https.request() silently fails - doesn't throw an error - and nothing is reported in the log.
The problem was that I was never completing the request with req.end().
const https = require('https')
function handler(event, context, callback) {
const options = {
hostname: 'encrypted.google.com',
method: 'GET'
}
https
.request(options, (res) => {
console.log('statusCode:', res.statusCode);
res.on('end', callback.bind(null, null))
})
.on('error', callback)
.end(); // <--- The important missing piece!
}
exports.handler = handler
Please try this one if your API is HTTPS,
var url = 'HTTPS URL HERE';
var req = https.get(url, (res) => {
var body = "";
res.on("data", (chunk) => {
body += chunk
});
res.on("end", () => {
var result = JSON.parse(body);
callBack(result)
});
}).on("error", (error) => {
callBack(err);
});
}
And if it is HTTP then,
var url = 'HTTP URL HERE';
var req = http.get(url, (res) => {
var body = "";
res.on("data", (chunk) => {
body += chunk
});
res.on("end", () => {
var result = JSON.parse(body);
callBack(result)
});
}).on("error", (error) => {
callBack(err);
});
}
Please don't fogot to add package require('https') / require('http')
The POST method is done by the request method.
This is the lambda code:
const https = require('https');
const options = {
hostname: 'Your host name',
path: '/api/v1/Login/Login',
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body : JSON.stringify({
'email': 'hassan.uzair9#gmail.com',
'password': 'Asdf1234.',
})
};
var result;
try{
result = await https.request(options);
console.log("result.....",result);
}catch(err){
console.log("err......",err);
}
Related
I'm new to AWS lambda functions and NodeJS. I'm trying to create an API Gateway call to a Lambda function that calls an external API and return some JSON data. It took me a while but I was finally able to get something to work based on this post:
AWS Lambda HTTP POST Request (Node.js)
The problem was the API Gateway kept erroring with a 502 Bad Gateway; which turns out to be that the JSON response was malformed. In the post I referenced above everyone seem to have success with just returning the JSON as-is, but I had to follow the instructions here to fix my issue:
https://aws.amazon.com/premiumsupport/knowledge-center/malformed-502-api-gateway/
My question is: if you look at the last 10 lines of my code that finally worked I had to reformat my response, as well as use a callback in a async function. I am new to nodeJS and Lambda but it looks wrong to me, even though it works. The post I referenced seem to have much more elegant code, and I hope someone can tell me what I am doing wrong.
const https = require('https');
var responseBody = {"Message": "If you see this then the API call did not work"};
const doGetRequest = () => {
return new Promise((resolve, reject) => {
const options = {
host: 'my.host.com',
path: '/api/v1/path?and=some¶meters=here',
method: 'GET',
headers: {
'Authorization': 'Bearer token for testing',
'X-Request-Id': '12345',
'Content-Type': 'application/json'
}
};
var body='';
//create the request object with the callback with the result
const req = https.request(options, (res) => {
res.on('data', function (chunk) {
body += chunk;
});
res.on('end', function () {
console.log("Result", body.toString());
responseBody = body;
});
resolve(JSON.stringify(res.statusCode));
});
// handle the possible errors
req.on('error', (e) => {
reject(e.message);
});
//finish the request
req.end();
});
};
exports.handler = async (event, context, callback) => {
await doGetRequest();
var response = {
"statusCode": 200,
"headers": {
"my_header": "my_value"
},
"body": JSON.stringify(responseBody),
"isBase64Encoded": false
};
callback(null, response);
};
I see couple of things.
We need to get the values from method doGetRequest and use the response, we can do that by await response = doGetRequest() or doGetRequest.then(), since we ant to capture errors as well, i went with second method.
We also need to resolve or reject the actual response from within promise.
I tested with a different api(with url of this question). Here is the updated code.
const https = require('https');
var responseBody = {"Message": "If you see this then the API call did not work"};
const doGetRequest = () => {
return new Promise((resolve, reject) => {
const options = {
host: 'stackoverflow.com',
path: '/questions/66376601/aws-api-gateway-with-lambda-http-get-request-node-js-502-bad-gateway',
method: 'GET'
};
var body='';
//create the request object with the callback with the result
const req = https.request(options, (res) => {
res.on('data', function (chunk) {
body += chunk;
});
res.on('end', function () {
console.log("Result", body.toString());
resolve(body);
});
});
// handle the possible errors
req.on('error', (e) => {
reject(e.message);
});
//finish the request
req.end();
});
};
exports.handler = (event, context, callback) => {
console.log('event',event, 'context',context);
doGetRequest().then(result => {
var response = {
"statusCode": 200,
"headers": {
"my_header": "my_value"
},
"body": JSON.stringify(result),
"isBase64Encoded": false
};
callback(null, response);
}).catch(error=> {
callback(error);
})
};
completely beginner question here, but im stuck for hours, hope someone can help!
I'm building some thing over AWS API Gateway + Lambda, where I receive a POST request on AWS and I send some data to another API.
I'm using https from NodeJS (from examples i found here on stackoverflow) but it doesnt seem to be working...I'm testing by sending it to a webhook inbox in beeceptor
Could you give me some light?
exports.handler = async (event) => {
if(event.httpMethod == 'POST'){
return pedido(event);
}
};
var aid = '';
var cep = '';
const pedido = event => {
let body = JSON.parse(event.body);
var aid = body.cid;
//var sku = body.items.id
var cep = body.cep;
callapi(cep,aid);
console.log("teste cep ", body.cep);
return{
statusCode: 200,
body: JSON.stringify({
message: body.cep,
convid: aid
})
};
};
function callapi(cep,aid){
const https = require('https');
const data = JSON.stringify({
message: cep,
convid: aid,
test: 123
});
console.log("data is ", data);
const options = {
hostname: 'testbot.free.beeceptor.com',
//port: 443,
path: '/',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': data.length
}
};
console.log("code was here ");
var req = https.request(options, (res) => {
console.log('req:', req);
console.log('res:', res);
console.log('statusCode:', res.statusCode);
console.log('headers:', res.headers);
res.on('data', (d) => {
process.stdout.write(d);
});
});
console.log('req:', req);
req.on('error', (e) => {
console.error(e);
});
req.write(data);
req.end();
}
There's at least one problem with your code:
The callapi function is making a request and this request is using a callback to notify you about a response. However, you are not waiting for it in your Lambda code and hence you won't see its response in your logs. Add appropriate awaits or Promises to it, so your code won't return before you've received a response.
The structure of your code could look similar to this:
exports.handler = async (event) => {
if (event.httpMethod === 'POST') {
return await pedido(event);
}
};
async function pedido(event) {
// init vars...
// wait for your API call
await callapi(cep, aid);
// then return a response
return {...}
}
async function callapi(cep, aid) {
// init vars like https and others...
// then use a promise and resolve it when you receive the request's callback (= response) or an error
return new Promise((resolve, reject) => {
const req = https.request(options, (res) => {
// handle response however you like ...
// then resolve the promise when you're done
resolve();
});
req.on('err', (e) => {
// reject in case the request fails
reject(e);
});
});
}
Does this solve your problem? If not, having some more logs of your method and a simplified code example would help a lot!
I am tying to call the external API from the lambda function for LEX bot intent and not able to communicate with external API, these APIs are hosted somewhere else. Same JS code is working from my local system, but not able to communicate from lambda function. so it is not an issue with the service, more like an issue in the AWS cloud network or something related. i looked at the cloud watch logs, but no errors are reported
I am not using VPC's my function is outside of VPC. any help would greatly appreciated
exports.handler = async (event) => {
console.log ("executing222222") ;
var https = require('https');
var options = {
'method': 'POST',
'hostname': 'ccc.com',
'path': '/xxx',
'headers': {
'Authorization': 'bearer6ad1a3ae-2a1d-48e0-bf68-8669c5b9af62'
}
};
console.log ("test");
var req = https.request(options, function (res) {
console.log ("test1111");
res.setEncoding('utf8');
var returnData = "";
res.on('data', function (chunk) {
returnData += chunk;
});
console.log ("test11");
res.on("end", function () {
var body = JSON.parse(returnData) ;
console.log(body.toString());
});
res.on("error", function (error) {
console.error(error);
});
});
req.end();
};
this code helps to resolve the async issue.
const http = require('http');
exports.handler = async (event, context) => {
return new Promise((resolve, reject) => {
const options = {
host: 'ec2-18-191-89-162.us-east-2.compute.amazonaws.com',
path: '/api/repos/r1639420d605/index?delta=true&clear=false',
port: 8000,
method: 'PUT'
};
const req = http.request(options, (res) => {
resolve('Success');
});
req.on('error', (e) => {
reject(e.message);
});
// send the request
req.write('');
req.end();
});
};`enter code here`
i'm trying to do a HTTPS request in nodejs as follows:
var makeRequest = options => {
const req = https.request(options, res => {
// console.log('statusCode:', res.statusCode);
// console.log('headers:', res.headers);
res.on('data', d => {
process.stdout.write(d);
});
});
req.on('error', e => {
console.error(e);
});
req.end();
// return results;
};
Instead of print it i would like to return this value to another function, that should looks like:
{items:[..,..,...]}
one way would be writing the function with the callback, where the function send the request ,as the response we will getting would be stream we would have store in the temporary variable, and after successfully getting the whole response, will have to pass the response to the callback function.
const https = require('https');
const StringDecoder = require('string_decoder').StringDecoder;
const options = {
hostname: 'encrypted.google.com',
port: 443,
path: '/',
method: 'GET'
};
function getData(callbackfun){
const req = https.request(options, (res) => {
const decoder = new StringDecoder('utf-8');
let responseData = '';
res.on('data', (data) => {
responseData += decoder.write(data);
});
res.on('end',function(){
responseData += decoder.end();
callbackfun(responseData)
})
});
req.on('error', (e) => {
callbackfun(e)
});
req.end()
}
getData((result)=>{
console.log(result);
})
In Azure function how to call an API using javascript. The request is POST with the header.I tried to use XMLHttpRequest, but i got exception like this XMLHttpRequest is not defined.
var client = new XMLHttpRequest();
var authentication = 'Bearer ...'
var url = "http://example.com";
var data = '{.........}';
client.open("POST", url, true);
client.setRequestHeader('Authorization',authentication);
client.setRequestHeader('Content-Type', 'application/json');
client.send(data);
Any other method is there to achive this,
You can do it with a built-in http module (standard one for node.js):
var http = require('http');
module.exports= function (context) {
context.log('JavaScript HTTP trigger function processed a request.');
var options = {
host: 'example.com',
port: '80',
path: '/test',
method: 'POST'
};
// Set up the request
var req = http.request(options, (res) => {
var body = "";
res.on("data", (chunk) => {
body += chunk;
});
res.on("end", () => {
context.res = body;
context.done();
});
}).on("error", (error) => {
context.log('error');
context.res = {
status: 500,
body: error
};
context.done();
});
req.end();
};
You can also use any other npm module like request if you install it into your Function App.