Error: getaddrinfo ENOTFOUND error when making an HTTPS/HTTP request - node.js

Here's the code of my AWS Lambda function:
console.log('Loading function');
const AWS = require('aws-sdk');
const https = require('https');
const data = JSON.stringify({
secretKey:"someSecretKey",
userType:"someCoolUser",
})
const options = {
hostname: "backend-staging.programmingpathshala.com:8080/rest/admin",
path: '/sendEmailToUsers',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': data.length
}
}
exports.handler = function(event, context, callback) {
var dataString = '';
const req = https.request(options, function(res) {
res.on('data', chunk => {
dataString += chunk;
});
res.on('end', () => {
callback(null,dataString);
});
});
req.write(data)
req.end();
req.on('error', (e) => {
console.error(e);
});
}
When I test my API using postman it works fine. But when it is called from lambda function I get the following error:
Also, When I run the same API using ngrok and use its link in my lambda function it works then too.

Based on the comments, the options should be:
const options = {
hostname: "backend-staging.programmingpathshala.com",
port: 8080,
path: '/rest/admin/sendEmailToUsers',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': data.length
}
}

Related

NodeJS request get return me html code instead of json

I'm trying to get get a json from a get request it's work in python but in NodeJs that display me the html code source of the page
this is my code :
app.get("/well", function(request, response) {
const req = require('request');
const options = {
url: 'https://swarmmanager.francecentral.cloudapp.azure.com:3000',
method: 'GET',
headers: {
'Accept': 'application/json',
},
agentOptions: {
ca: fs.readFileSync("public/IdaktoPKIRootCA.crt")
}
};
req(options, function(err, res, body) {
console.log(body);
});
});
and this is another version but same problem:
app.get("/well", function(request, response) {
g_CnieOidcAddr = 'https://swarmmanager.francecentral.cloudapp.azure.com:3000';
const options = {
hostname: 'swarmmanager.francecentral.cloudapp.azure.com',
port: 3000,
method: 'GET',
headers: {
'Accept': 'application/json',
},
ca: fs.readFileSync("public/IdaktoPKIRootCA.crt")
};
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();
});
i try to do it in python and it's work find that return me a json:
headers = {'Accept': 'application/json'}
r = requests.get(g_CnieOidcAddr + '/.well-known/openid-configuration', params={}, headers = headers, verify='./IdaktoPKIRootCA.crt')
print (r.text)
if anyone has an idea i'm a taker ^^ thanks for reading.
ok that work find i just forgot something at the end of the url so if you come to this page the 2 codes work find to to a request

error using nodejs to do http post request

I have followed some instructions to do http request in nodejs and I am doing it in TypeScript in the following way:
code that calls the function to do http post call:
const getCaseInfoRequest: GetCaseInfoRequest = {
emailAddress: 'some-email-address#amazon.com'
};
makeCardinalCall('/SalesforceCaseService/1.0/GetCaseInfoFromEmail', getCaseInfoRequest, process.env.STAGE)
.then((data) => {
...
}).catch(...);
the function that does http post call:
export function makeCardinalCall(path: string, requestBody: GetCaseInfoRequest, stage?: string) {
return new Promise((resolve, reject) => {
const data = JSON.stringify(requestBody);
const options: http.RequestOptions = {
host: 'my-service.google.com',
port: 443,
path: path,
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': data.length,
}
};
const req = http.request(options, (res: http.IncomingMessage) => {
res.setEncoding("utf8");
let data = '';
res.on('data', chunk => {
data += chunk;
});
res.on('end', () => {
resolve(data);
})
});
req.on('error', (e: any) => {
reject(e);
});
req.end(data);
});
}
but i always got the following error:
{"bytesParsed":0,"code":"HPE_INVALID_CONSTANT","reason":"Expected HTTP/","rawPacket":{"type":"Buffer","data":[21,0,0,0,2,1,0]}}
any hint / help would be greatly appreciated!
You're attempting to use the raw http module with an HTTPS endpoint (as evident from the port 443). The HTTP parser fails to parse the TLS bytes coming over the wire.
For your own sanity's sake, use a wrapper module for requests -- such as node-fetch...

Invoking Spotify API from lambda function

I need to get data from Spotify API then send the response to the front-end. To avoid CORS issue and to hide key and secret from Spotify, I would like to use Lambda to make the API call then send back the response. To be more precise about my application:
1. FrontEnd > API Gateway
2. API Gateway > Lambda
3. Lambda > Spotify API (request their API to get token)
4. Spotify API > Lambda (token in the response)
5. Lambda > API Gateway
6. API Gateway > FrontEnd
Spotify endpoint is:
https://accounts.spotify.com/api/token?grant_type=client_credentials
Header is:
Content-Type: 'application/x-www-form-urlencoded'
Authorization: 'Basic XXX'
So far I was able to do this using a Lambda function:
const https = require('https');
exports.handler = async (event, context) => {
return new Promise((resolve, reject) => {
const options = {
hostname: 'accounts.spotify.com',
path: '/api/token?grant_type=client_credentials',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Basic XXX'
}
}
const req = https.request(options, (res) => {
res.on('data', function (chunk) {
console.log('BODY: ' + chunk);
});
resolve('Success');
});
req.on('error', (e) => {
reject(e.message);
});
// send the request
req.write('');
req.end();
});
};
But I can't get the response from the API:
{
"access_token": "YYY",
"token_type": "Bearer",
"expires_in": 3600,
"scope": ""
}
And I don't know how to send the data back to the front-end. Do you have any guidance to achieve what I'm looking for?
Edit: I also tried using axios as suggested:
const axios = require("axios");
module.exports.handler = (event, context, callback) => {
const headers = {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Basic XXX'
}
axios.post('https://accounts.spotify.com/api/token?grant_type=client_credentials', {}, {
headers: headers
})
.then(function(response) {
console.log(response)
callback(null, response);
})
.catch(function(err) {
console.error("Error: " + err);
callback(err);
});
};
But got the following error:
Response:
{
"errorType": "Error",
"errorMessage": "Request failed with status code 400",
"trace": [
"Error: Request failed with status code 400",
" at createError (/var/task/node_modules/axios/lib/core/createError.js:16:15)",
" at settle (/var/task/node_modules/axios/lib/core/settle.js:17:12)",
" at IncomingMessage.handleStreamEnd (/var/task/node_modules/axios/lib/adapters/http.js:237:11)",
" at IncomingMessage.emit (events.js:215:7)",
" at endReadableNT (_stream_readable.js:1183:12)",
" at processTicksAndRejections (internal/process/task_queues.js:80:21)"
]
}
Thanks to #jarmod and #Ashish Modi, the solution below is working for me:
const axios = require("axios");
const querystring = require('querystring');
module.exports.handler = (event, context, callback) => {
const headers = {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Basic XXX'
}
axios.post('https://accounts.spotify.com/api/token?grant_type=client_credentials', querystring.stringify({}), {
headers: headers
})
.then(function(response) {
const res = {
statusCode: 200,
body: (response.data.access_token)
};
callback(null, res);
})
.catch(function(err) {
console.error("Error: " + err);
callback(err);
});
};
try this
const https = require('https');
function hitApi() {
return new Promise((resolve, reject) => {
const options = {
hostname: 'accounts.spotify.com',
path: '/api/token?grant_type=client_credentials',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Basic XXX'
}
}
https.request(options, (res) => {
res.setEncoding("utf8");
let body = "";
res.on('data', function (chunk) {
body += chunk;
});
res.on("error", err => {
reject(err);
});
res.on('end', function () {
resolve(body);
});
});
});
}
exports.handler = async (event, context) => {
const result = await hitApi();
return result;
};
hope this helps

Node Express Get request passing a custom header

I am trying to make a get request equivalent to this jQuery:
$.ajax({
headers: { 'X-Auth-Token': 'YOUR_API_KEY' },
url: 'http://api.football-data.org/v2/competitions/BL1/standings',
dataType: 'json',
type: 'GET',
}).done(function(response) {
console.log(response);
});
However, I haven't figured out how to do it using nodejs - express. This code is from an api routes module attached to the main app.
The request seems to work, collecting the data but does not end. Also, I cannot see the custom header in the request when inspecting from the browser.
app.get('/api/:league', function(req, res, next) {
var apiKey = process.env.API_KEY;
let url = 'api.football-data.org';
var options = {
host: url,
method: 'GET',
path: 'v2/competitions/BL1/standings',
headers: {
'X-Auth-Token': apiKey
}
};
let data = "";
var getReq = http.request(options,function(resp){
console.log("Connected");
resp.on("data", chunk => {
data += chunk;
});
resp.on("end", () => {
console.log("data collected");
});
});
getReq.on("error", (err) => console.log("OOPS!", err));
getReq.end(JSON.stringify(data));
})
Link to project
Try using request-promise npm package.https://www.npmjs.com/package/request-promise
var rp = require(request-promise);
const baseUrl = 'api.football-data.org/v2/competitions/BL1/standings';
const apiKey = process.env.API_KEY;
var options = {
method: 'GET',
uri: baseUrl,
headers: {
'X-Auth-Token': apiKey
},
json: true
};
rp(options)
.then(function (response) {
console.log(response)
}
);
jQuery ajax function does not have headers option. You can read about this function on official doc http://api.jquery.com/jquery.ajax/ . They custom request header by beforeSend function way:
$.ajax({
beforeSend: function (request) {
request.setRequestHeader("X-Auth-Token", 'YOUR_API_KEY');
},
url: 'http://api.football-data.org/v2/competitions/BL1/standings',
dataType: 'json',
type: 'GET',
}).done(function (response) {
console.log(response);
});
With http node lib, you can flow this example
var req = http.request(options, function (res) {
var chunks = [];
res.on("data", function (chunk) {
chunks.push(chunk);
});
res.on("end", function () {
var body = Buffer.concat(chunks);
// TODO: send data to client
// res.status(200).json(JSON.stringify(body.toString()))
console.log(body.toString());
});
});
req.end();

NodeJS Patreon API account link

I'm trying to connect user accounts on my website to patreon. I keep getting an access_denied error message in response to step 3. I'm following this documentation.
My node server code looks like this:
socket.on("patreon_register",function(code,user){
var reqString = "api.patreon.com/oauth2/token?code="
+code
+"&grant_type=authorization_code&client_id="
+settings.patreon.Client_ID
+"&client_secret="
+settings.patreon.Client_Secret
+"&redirect_uri="
+"http%3A%2F%2Fwww.levisinger.com%2F%3Fpage%3Dpatreon_success",
req = querystring.stringify({
"code": code,
"grant_type": "authorization_code",
"client_id": settings.patreon.Client_ID,
"client_secret": settings.patreon.Client_Secret,
"redirect_uri": "http%3A%2F%2Fwww.levisinger.com%2F%3Fpage%3Dpatreon_success"
}),
post_options = {
host: 'api.patreon.com',
port: '80',
path: '/oauth2/token',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(req)
}
};
// Set up the request
console.log(req);
var post_req = http.request(post_options, function(res) {
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log(chunk);
if(
chunk.access_token &&
chunk.refresh_token &&
chunk.expires_in &&
chunk.scope &&
chunk.token_type
){
Auth.linkPatreon(user,chunk,function(err,res){
if(err){ socket.emit('patreon_register',false,res); }
else { socket.emit('patreon_register',true,res); }
});
}
});
});
// post the data
post_req.write(req);
post_req.end();
});
The req variable that's actually sent to the server looks like this (changed my codes to generic values of course)
code=MY_RESPONSE_CODE&grant_type=authorization_code&client_id=MY_CLIENT_ID&client_secret=MY_CLIENT_SECRET&redirect_uri=MY_RESPONSE_URI
Any ideas?
In the end, my server looks like this and is working:
socket.on("patreon_register",function(code,user){
var req = querystring.stringify({
code: code,
grant_type: "authorization_code",
client_id: settings.patreon.Client_ID,
client_secret: settings.patreon.Client_Secret,
redirect_uri: settings.patreon.redirect_uri
}),
post_options = {
host: 'api.patreon.com',
port: '80',
path: '/oauth2/token',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(req)
}
};
// Set up the request
console.log(req);
var post_req = http.request(post_options, function(res) {
res.setEncoding('utf8');
res.on('data', function (chunk) {
chunk = JSON.parse(chunk);
console.log(chunk);
if(!chunk["error"]){
console.log("Linking!");
Auth.linkPatreon(user,chunk,function(err,res){
if(err){ socket.emit('patreon_register',false,res); }
else { socket.emit('patreon_register',true,res); }
console.log("Linked!");
});
}
});
});

Resources