Node Call Export on Callback - javascript

I'm banging my head for not learning from the basics and just jumping in.
I'm building an API that returns the SSL Certificate status of a domain.
It's working fine on console.log but the JSON output is empty, obviously because the exports get executed before the https request ends.
How do I incorporate the exports in response.on(end) function?
Thanks a lot!
function getSSL(domain) {
var options = {
host: 'www.'+domain+'.com',
method: 'get',
path: '/'
};
var isAuth = false;
callback = function(response) {
response.on('data', function () {
isAuth = response.socket.authorized;
});
response.on('end', function () {
console.log(isAuth);
});
}
var req = https.request(options, callback).end();
}
exports.findByDomain = function (req, response) {
var id = req.params.id;
sslCheck = getSSL(id);
response.send(sslCheck);
};

Yes, the response.send(sslCheck); gets executed before getSSL(id); has a chance to finish. You need to send in a callback so it can be executed after getSSL(id); finishes:
function getSSL(domain, callback) {
var options = {
host: 'www.'+domain+'.com',
method: 'get',
path: '/'
};
var isAuth = false;
var httpCallback = function(response) {
response.on('data', function () {
isAuth = response.socket.authorized;
});
response.on('end', function () {
console.log(isAuth);
callback(isAuth);
});
}
var req = https.request(options, httpCallback).end();
}
exports.findByDomain = function (req, response) {
var id = req.params.id;
getSSL(id, function(sslCheck) {
response.send(sslCheck);
});
};

Related

send response from nodejs express to angular app

I am calling an api of sending OTP from my nodejs app. I need to send the response of that OTP Api to the angular app.
my api service on angular look like this:
sendOtp(params): Observable<any> {
return this.apiService.post("/user/send-otp", params)
}
my router on express app look like this
this.router.post("/user/send-otp", userController.sendOtpMessage);
and the code inside userController look like this.
static sendOtpMessage(req, res ,next) {
const phone = req.body.phone;
var http = require("https");
var options = {
"method": "GET",
"hostname": "api.msg91.com",
"port": null,
"path": `/api/v5/otp?mobile=${phone}`,
"headers": {
"content-type": "application/json"
}
};
var callOtpApi = http.request(options, function (res) {
var chunks = [];
res.on("data", function (chunk) {
chunks.push(chunk);
});
res.on("end", function () {
var body = Buffer.concat(chunks);
console.log(body.toString());
// I need to send this data in response to my angular app ==>> body.toString()
});
});
callOtpApi.write();
callOtpApi.end();
}
OTP Api ref document: https://docs.msg91.com/p/tf9GTextN/e/B1NUt3C8MY/MSG91
It seems that the code above is missing the res.send() to return the data from server. Could you please try with this?
static sendOtpMessage(req, res ,next) {
const serverRes = res;
// Rest of your code
...
var callOtpApi = http.request(options, function (res) {
// Rest of your code
...
res.on("end", function () {
var body = Buffer.concat(chunks);
console.log(body.toString());
// Return data to client
serverRes.send(body.toString());
});
// Rest of your code
...
});
}
You can call the msg91 api using axios
const axios = require('axios');
async function sendOtpTOUser(phone) {
const template = "template _id";
const apiKey = "api_key";
const sendotp = "https://api.msg91.com/api/v5/otp?template_id="+template+"&mobile="+phone+"&authkey="+apiKey;
let request_options1 = {
method: 'get',
url: sendotp
};
let otpResponse = await axios(request_options1);
console.log(otpResponse.data)
return otpResponse.data;
}
it will return the object as
{ request_id: '3166686e7867313634383535', type: 'success' }

How to get a variable out of http request NodeJS?

I would like to use two IBM Watson services and combine the responses from both in one variable and return it as a callback. I couldn't figure out how to get response1 value outside the http request to combine it with response2 from the other IBM Watson service.
I tried the below code and it didn't work. I read that I can use promises, but I'm pretty new to this, and couldn't figure out how to do this.
Can anyone help please?
const AWS = require('aws-sdk');
var http = require('https');
exports.handler = (event, context, callback) => {
var text = JSON.stringify(event.text);
var options = {
method: process.env.method,
hostname: process.env.watson_hostname,
port: null,
path: process.env.path,
headers: {
'content-type': process.env.content_type,
authorization: process.env.authorization,
'cache-control': process.env.cache_control,
'X-Watson-Learning-Opt-Out': 'true'
}
};
var req = http.request(options, function (res) {
var chunks = "";
res.on("data", function (chunk) {
chunks+ = chunk.toString();;
});
res.on("end", function () {
var response1 = (chunks);
//////////////here I need to get reponse2
var response2 = IBM2();
var bothResponses = response1 + response2
callback(null,bothResponses)
});
})
req.write(text);
req.end()
function IBM2(){
var text = JSON.stringify(event.text);
var options = {
method: process.env.method2,
hostname: process.env.watson_hostname2,
port: null,
path: process.env.path2,
headers: {
'content-type': process.env.content_type2,
authorization: process.env.authorization2,
'cache-control': process.env.cache_control,
'X-Watson-Learning-Opt-Out': 'true'
}
};
var req = http.request(options, function (res) {
var chunks = [];
res.on("data", function (chunk) {
chunks.push(chunk);
});
res.on("end", function () {
var response2 = JSON.parse(Buffer.concat(chunks));
return(response2)
}
Return a promise from your IBM2 function and handle using async await in the calling function. Notice the async keyword before on end callback.
I have tried to add Promise to your existing flow:
const AWS = require('aws-sdk');
var http = require('https');
exports.handler = (event, context, callback) => {
var text = JSON.stringify(event.text);
var options = {
method: process.env.method,
hostname: process.env.watson_hostname,
port: null,
path: process.env.path,
headers: {
'content-type': process.env.content_type,
authorization: process.env.authorization,
'cache-control': process.env.cache_control,
'X-Watson-Learning-Opt-Out': 'true'
}
};
var req = http.request(options, function (res) {
var chunks = "";
res.on("data", function (chunk) {
chunks += chunk.toString();;
});
res.on("end", async function () {
var response1 = (chunks);
//////////////here I need to get reponse2
var response2 = await IBM2();
// validate response2 (in case IBM2 throws error)
var bothResponses = response1 + response2;
callback(null,bothResponses)
});
});
req.write(text);
req.end();
function IBM2(){
return new Promise((resolve, reject) =>{
var text = JSON.stringify(event.text);
var options = {
method: process.env.method2,
hostname: process.env.watson_hostname2,
port: null,
path: process.env.path2,
headers: {
'content-type': process.env.content_type2,
authorization: process.env.authorization2,
'cache-control': process.env.cache_control,
'X-Watson-Learning-Opt-Out': 'true'
}
};
var req = http.request(options, function (res) {
var chunks = [];
res.on("data", function (chunk) {
chunks.push(chunk);
});
res.on("end", function () {
var response2 = JSON.parse(Buffer.concat(chunks));
resolve(response2)
});
res.on("error", function (err) {
reject(err);
});
})
});
}
};
Before making any changes to your code, I would suggest you go thru these topics first.
For reference, do take a look into the concept of promises and async-await
Promiese
Async/Await
Dont know if you have other errors, but it looks like youre not waiting for response2 to finish, maybe something like
const response2 = await IBM2():
or if you want to use promises maybe something like:
res.on('end', function () {
var response2 = IBM2().then(
val => {
var bothResponses = response1 + val;
callback(null, bothResponses);
},
reject => {
/* handle rejection here */
},
);
});

Node js sending multiple requests after 20 secs

My node js app is making multiple http request if there is delay in response of say 20 secs. Below is the sample code for the same.
First I make call to the getAPI function from browser. getApi function calls the getAccessToken API, after receiving the accesstoken I am calling the testApi. Now if there is a delay of 20 secs in response from testApi then getAccessToken Api is getting called again. I don't want to use promise. Can anyone point out what I am missing or doing wrong here?
shttp = require('http-https');
exports.getAPI = function(typeObj, request, response, callback) {
var userConf; //contains info such as port, host, url etc
_this.getAccessToken(function(tokenResponse) {
var tokenInfo = JSON.parse(tokenResponse);
var accessToken = JSON.parse(tokenInfo.response);
accessToken = accessToken.access_token;
if(accessToken) {
_this.testApi(userConf,accessToken,function(sjmResponse) {
callback(sjmResponse);
}
} else {
callback(JSON.stringify({"payLoad":null,"reasonCode":"fail","status":null}));
}
});
};
exports.getAccessToken = function(cb) {
var tokenConf; //contains info such as port, host, url etc
var httpReq = shttp.request(tokenConf, function(res) {
res.setEncoding('utf8');
if (res.statusCode == 200) {
var body = "";
res.on('data', function (result) {
body += result;
});
res.on('end', function (){
cb(JSON.stringify({error: '', response: (body)}));
});
} else {
cb(JSON.stringify({error: 'Failed to get user access token '+res.statusCode, response:''}));
}
});
httpReq.on('error', function(e) {
cb(JSON.stringify({error: 'Failed to get user access token'+e, response:''}));
});
httpReq.end();
};
exports.testApi = function(userConf,accessToken,sjmCallback) {
var userConf; //contains info such as port, host, url etc
var httpSubmitReq = shttp.request(userConf, function(res) {
res.setEncoding('utf8');
if (res.statusCode == 200) {
var body = "";
res.on('data', function (result) {
body += result;
});
res.on('end', function () {
sjmCallback(body);
});
} else {
sjmCallback(JSON.stringify({"payLoad":null,"reasonCode":"fail","status":null}));
}
});
httpSubmitReq.on('error', function(e) {
sjmCallback(JSON.stringify({"payLoad":null,"reasonCode":"fail","status":null}));
});
httpSubmitReq.end();
};
app.get('/testApi', function (req, res) {
var typeObj = {};
typeObj.apiType= 'testApi';
try {
getAPI(JSON.stringify(typeObj), req, res, function(response) {
res.end(response);
});
} catch(err) {
res.end(err);
}
});

Using the results of a GET request in Express router

First Node/Express app.
I'm having a hard time wrapping my head around on how to retrieve data from an endpoint and rendering it in the browser.
I have a dataservice.js that gets a JSON object from an endpoint like this:
const http = require('http');
getFinhockeyData = function() {
http.get('http://tilastopalvelu.fi/ih/modules/mod_standings/helper/standings.php?statgroupid=3545', (res) => {
console.log(`Got response: ${res.statusCode}`);
var body = "";
res.on('data', function (chunk) {
body += chunk;
})
res.on('end', function () {
var data = JSON.parse(body);
console.log('data parsed.');
console.log('first team name: ' + data.teams[0].TeamName);
console.log(typeof data);
return data;
})
}).on('error', (e) => {
console.log(`Got error from Finhockey: ${e.message}`);
});
}
module.exports.getFinhockeyData = getFinhockeyData;
Up until now things work and the data object can be console.logged and its content is usable.
The router.js looks currently like this:
'use strict';
const express = require('express');
const async = require('async');
const router = express.Router();
const dataservice = require('./dataservice.js')
router.get('/', function(req, res) {
async.series([
function(callback) {
getFinhockeyData(callback)
}
],
function(err, results) {
console.log('start rendering');
res.render('index', { data: data });
})
});
module.exports = router;
When I run the app and refresh the / route, I can see from the console that the getFinhockeyData is called and the data object's content is available in dataservice.js's console.logs, but the browser window hangs and the res.render part is never reached.
I understand that the rendering should be done only after the endpoint data request has finished (async.series usage), but it seems that I lack a fundamental understanding on how to actually use the result data from the getFinhockeyData function in the main route.
Any advice on this? I'll be happy to provide more info if necessary.
Firstly, doing the request is asynchronous, so you'll have to use either a callback or a promise.
Even the async middleware won't let you just return data from an asynchronous call, it requires a callback, but using native promises seems easier here
const http = require('http');
getFinhockeyData = function() {
return new Promise( (resolve, reject) => {
http.get('http://tilastopalvelu.fi/ih/modules/mod_standings/helper/standings.php?statgroupid=3545', (res) => {
var body = "";
res.on('data', function(chunk) {
body += chunk;
});
res.on('end', function() {
resolve( JSON.parse(body) );
});
}).on('error', reject);
});
}
module.exports.getFinhockeyData = getFinhockeyData;
Also note that you're exporting as a module with a property
module.exports.getFinhockeyData = getFinhockeyData;
when you're going to use that in the routes, you have to use the property
const dataservice = require('./dataservice.js');
router.get('/', function(req, res) {
dataservice.getFinhockeyData().then(function(data) {
res.render('index', { data: JSON.stringify(data) });
}).catch(function(err) {
// epic fail, handle error here
});
});
You are responding to your route call with
res.render('index', { data: data });
But there is no data variable. It should be
res.render('index', { data: results });
Which is the variable where you are storing your data when it comes from the callback
The reason for res.render() not being called is, http requests are async. To get the response a callback must be passed, which you did but forgot to call it in the dataservice.js
This should help...
Change your dataservice.js like the following...
const http = require('http');
getFinhockeyData = function(callback) {
http.get('http://tilastopalvelu.fi/ih/modules/mod_standings/helper/standings.php?statgroupid=3545', (res) => {
console.log(`Got response: ${res.statusCode}`);
var body = "";
res.on('data', function (chunk) {
body += chunk;
})
res.on('end', function () {
var data = JSON.parse(body);
console.log('data parsed.');
console.log('first team name: ' + data.teams[0].TeamName);
console.log(typeof data);
callback(null, data); //returning the data to the callback
})
}).on('error', (e) => {
console.log(`Got error from Finhockey: ${e.message}`);
callback(e, null);
});
}
module.exports.getFinhockeyData = getFinhockeyData;
Change your router.js like the following...
router.get('/', function(req, res) {
async.series([
function(callback) {
getFinhockeyData(callback)
}
],
function(err, results) {
if(err === null){
console.log('start rendering');
res.render('index', { data: results[0] });
}
})
});

Aborting pending http request in Angular not aborting

I am trying to abort an $https request in Angular when a new request is triggered. However, the request still appears to be pending in Chrome's dev tool. Am I doing anything wrong here?
allMarkersRequest.abort() gets fired when allMarkersRequest is not null. So deferredAbort.resolve() is called, but the program still ends up going through .then().
var allMarkersRequest = null;
function getAllMarkersForSearch() {
if (allMarkersRequest) {
allMarkersRequest.abort();
console.log('Aborting all markers request');
}
var deferredAbort = $q.defer();
var url = Routing.generate('ajax_search_geo_all_markers');
var req = $http({
method: 'POST',
url: url
});
allMarkersRequest = req.then(function (data) {
createMarkers(data.data);
$rootScope.$broadcast('map:markers:updated', markers);
}, function (error) {
// Display error message
});
allMarkersRequest.abort = function() {
deferredAbort.resolve();
};
allMarkersRequest.finally(function () {
allMarkersRequest.abort = angular.noop;
deferredAbort = req = allMarkersRequest = null;
});
}
I did not include the timout parameter in request
var allMarkersRequest = null;
function getAllMarkersForSearch() {
if (allMarkersRequest) {
allMarkersRequest.abort();
console.log('Aborting all markers request');
}
var deferredAbort = $q.defer();
var url = Routing.generate('ajax_search_geo_all_markers');
var req = $http({
method: 'POST',
url: url,
timeout: deferredAbort
});
allMarkersRequest = req.then(function (data) {
createMarkers(data.data);
$rootScope.$broadcast('map:markers:updated', markers);
}, function (error) {
// Display error message
});
allMarkersRequest.abort = function() {
deferredAbort.resolve();
};
allMarkersRequest.finally(function () {
allMarkersRequest.abort = angular.noop;
deferredAbort = req = allMarkersRequest = null;
});
}

Categories

Resources