Cannot view data on page after adding API requests nodejs - node.js

I've added API requests which would retrieve data from MongoDB I believe. Whilst no issues arise when running the code, the pages do not show any data; I just get an error message (retrieved from a separate piece of code) stating the page cannot be found.
This is the code from my Locations controller:
module.exports.homelist = function(req, res){
var requestOptions, path;
path = '/api/locations';
requestOptions = {
url : apiOptions.server + path,
method : "GET",
json : {},
qs : {
lng : -0.7992599,
lat : 51.378091,
maxDistance : 20
}
};
request (
requestOptions,
function(err, response, body) {
var i, data;
data = body;
if(response.statusCode === 200 && data.length){
for (i=0; i<data.length; i++) {
data[i].distance = _formatDistance(data[i].distance);
}
}
renderLocHomepage(req, res, body);
}
);
var _formatDistance = function (distance){
var numDistance, unit;
if (distance > 1){
numDistance = parseFloat(distance).toFixed(1);
unit = 'km';
} else {
numDistance = parseInt(distance * 1000,10);
unit = 'm';
}
return numDistance + unit;
}
};
var renderLocHomepage = function(req, res, responseBody){
var message;
if(!(responseBody instanceof Array)){
message = "API lookup error";
responseBody = [];
} else {
if (!responseBody.length) {
message = "No places found nearby";
}
}
res.render('location', {
title: 'Location Title 2',
pageHeader: {
title: 'fuiewhf',
strapline: 'sdjkcdivfdvdj'
},
sidebar: "efvibjdmkdsuidjvifdvhiskfbvzd",
locations: responseBody,
message: message
});
};
/* GET 'Locations List' page*/
module.exports.locationsList = function(req, res) {
res.render('locations-list', {title: 'Locations List'});
};
module.exports.locationInfo = function(req, res){
renderDetailPage(req, res);
};
var renderDetailPage = function (req, res, locDetail){
res.render('location-info', {
title: locDetail.name,
pageHeader: {title: locDetail.name},
sidebar: {
context: 'is on Loc8r because it has some accessible wifi and space to sit',
callToAction: 'If you\'ve been and you like it or don\'t, please leave a review'
},
location: locDetail
});
};
/*GET 'Location info' page */
module.exports.locationInfo = function(req, res){
var requestOptions, path;
path = "/api/locations/" + req.params.locationid;
requestOptions = {
url : apiOptions.server + path,
method : "GET",
json : {}
};
request (requestOptions, function(err, response, body) {
var data = body;
if (response.statusCode === 200){
data.coords = {
lng : body.coords[0],
lat : body.coords[1],
};
renderDetailPage(req, res, data);
} else{
_showError(req, res, response.statusCode);
}
}
);
};
module.exports.locationsListByDistance = function(req, res){
var lng = parseFloat(req.query.lng);
var lat = parseFloat(req.query.lat);
var point = {
type: "Point",
coordinates: [lng, lat]
};
var geoOptions = {
spherical: true,
maxDistance: theEarth.getRadsFromDistance(20),
num: 10
};
if ((!lng && lng!==0) || (!lat && lat!==0)) {
sendJsonResponse(res, 404, {
"message": "lng and lat query parameters are required"
});
return;
}
Location.geoNear(point, geoOptions, function(err, results, stats){
var locations = [];
if (err) {
sendJsonResponse(res, 404, err);
} else {
results.forEach(function(doc) {
locations.push({
distance: theEarth.getDistanceFromRads(doc.dis),
name: doc.obj.name,
address: doc.obj.address,
rating: doc.obj.rating,
facilities: doc.obj.facilities,
_id: doc.obj._id
});
});
sendJsonResponse(res, 200, locations);
}
});
};
var _formatDistance = function (distance){
var numDistance, unit;
if (distance > 1){
numDistance = parseFloat(distance).toFixed(1);
unit = 'km';
} else {
numDistance = parseInt(distance * 1000,10);
unit = 'm';
}
return numDistance + unit;
};
//defining a call to an API
var requestOptions = {
url: "", //define URL of API call to be made
method: "GET", //set request method
json: {},
qs: {
offset: 20
}
};
request(requestOptions, function(err, response, body) {
if(err){
console.log(err);
} else if(response.statusCode === 200) {
console.log(body);
} else {
console.log(response.statusCode);
}
});
//Create a new reusable function to get location information
var getLocationInfo = function(req, res, callback) {
var requestOptions, path;
path = "/api/locations/" + req.params.locationid;
requestOptions = {
url : apiOptions.server + path,
method : "GET",
json : {}
};
request (
requestOptions,
function(err, response, body) {
var data = body;
if (response.statusCode === 200) {
data.coords = {
lng : body.coords[0],
lat : body.coords[1]
};
callback(req, res, data);
} else {
_showError(req, res, response.statusCode);
}
}
);
};
module.exports.locationInfo = function(req, res){
getLocationInfo(req, res, function (req, res, responseData){
renderDetailPage(req, res, responseData);
});
};

In renderHomepage you have res.render('/'... but res.render takes as first parameter the name of the file you want to render (minus the file extension):
res.render('index', ...
if your homepage is under views/index.ejs for example.

Related

How to consume a RESTful API in Node.js

I'm new to Node.js and I'm creating a simple pagination page. The REST API works fine, but consuming it has left me in limbo.
Here is the REST API (other parts have been taken out for brevity)
const data = req.query.pageNo;
const pageNo =
(typeof data === 'undefined' || data < 1) ? 1 : parseInt(req.query.pageNo);
let query = {};
const total = 10;
query.skip = (total * pageNo) - total;
query.limit = total;
try {
const totalCount = await Users.countDocuments();
const pageTotal = Math.ceil(totalCount / total);
const users = await Users.find({}, {}, query);
return res.status(200).json(users);
} catch (error) {
console.log('Error ', error);
return res.status(400).send(error)
};
};
When I return the json with just the 'users' object, like so return res.status(200).json(users); the page renders correctly, but when I pass in other objects like what I have in the code, it fails. This is how I'm consuming the API:
const renderHomepage = (req, res, responseBody) => {
let message = null;
if (!(responseBody instanceof Array)) {
message = 'API lookup error';
responseBody = [];
} else {
if (!responseBody.length) {
message = 'No users found nearby';
}
}
res.render('users-list', {
title: 'Home Page',
users: responseBody,
message: message
});
}
const homelist = (req, res) => {
const path = '/api/users';
const requestOptions = {
url: `${apiOptions.server}${path}`,
method: 'GET',
json: true,
};
request(
requestOptions,
(err, {statusCode}, body) => {
if (err) {
console.log('Ther was an error ', err);
} else if (statusCode === 200 && body.length) {
renderHomepage(req, res, body);
} else if (statusCode !== 200 && !body.length) {
console.log('error ',statusCode);
}
}
);
}
I've searched extensively on both here and other resources but none of the solutions quite answers my question. I hope someone could be of help

Parent function is not waiting for child to finish

Inside getMetadata(), Object.keys function is not waiting for httprequest to finish. How can I make object.keys function to wait till httprequest function manipluates the result variable?
I'm using node. I tried to make promise but failed.
function fetchAirportPageIDsListWithMetaJSON(faa, cb){
logger.info('[airportcms-data-processor] fetching airport pages list with Metadata');
var faa = faa
async.waterfall([
getAirportPageIDsList,
getMetadata,
], function (err, result) {
cb(null, result);
});
function getAirportPageIDsList(callback) {
httpRequests.fetchData('//s3 url to fetch data', function (err, data) {
var idsMap={};
data["page-ids"].forEach( (obj) => {
obj.list.forEach((item) => idsMap[item] = obj.id);
});
callback(null, idsMap);
})
}
function getMetadata(data,callback) {
var result=[];
Object.keys(data).sort().forEach( function (t) {
var tempJson={};
var urlcheck = verifySpecialPageId(t);
if (urlcheck){
var url = config.urls.s3_airports_base_url+'/'+faa+'/'+urlcheck;
}else{
var url = config.urls.s3_airports_base_url+'/'+faa+'/'+t;
}
tempJson["sectionId"]= t;
tempJson["page"]= data[t];
httpRequests.makeHeadRequestWithCallerId(url, function (err, metax) {
if (metax){
let z = metax.split('|')[0];
tempJson["SummaryRange"]= getSummaryRangeAirportPageList(z);
tempJson["timestamp"]= new Date(parseInt(z)).toLocaleDateString();
tempJson["callerId"]= metax.split('|')[1];
}else{
tempJson["timestamp"]='';
tempJson["callerId"]='';
tempJson["SummaryRange"]='';
}
})
result.push(tempJson);
});
logger.info("Final result: ", result);
callback(null, result);
}
}
http request function:
function makeHeadRequestWithCallerId (url, cb) {
httpRequest.head(url, function (err, res) {
if (err) {
logger.error('Error ' + err);
return cb(err, null);
}
if(res.code === 200) {
if (res.headers['x-amz-meta-x-amz-meta-lastmodified'] || res.headers['x-amz-meta-x-amz-meta-callerid']) {
var dateModified = res.headers['x-amz-meta-x-amz-meta-lastmodified'];
var timeStamp = Date.parse(dateModified);
var callerid = res.headers['x-amz-meta-x-amz-meta-callerid'];
if(timeStamp && callerid) {
return cb(null, timeStamp+'|'+callerid);
} else if (callerid){
return cb(null, '|'+callerid);
}else if(timeStamp){
return cb(null, timeStamp+'|');
}else{
return cb(null, null);
}
}else{
return cb(null, null);
}
}
});
}
Current log=> Final result:
[{ sectionId: 'internet-wifi', page: 'internet-wifi' },
{ sectionId: 'layover-ideas', page: 'layover-ideas' }]
Expected log=> Final result:
{ sectionId: 'internet-wifi',
page: 'internet-wifi',
SummaryRange: '12-99',
timestamp: '1/29/2018',
callerId: '' },
{ sectionId: 'layover-ideas',
page: 'layover-ideas',
SummaryRange: '12-99',
timestamp: '1/26/2017',
callerId: '' },
function getMetadata(data, callback) {
var result = [];
var count = Object.keys(data).length;
var i = 0;
Object.keys(data).sort().forEach(function (t) {
var tempJson = {};
var urlcheck = verifySpecialPageId(t);
if (urlcheck) {
var url = config.urls.s3_airports_base_url + '/' + faa + '/' + urlcheck;
} else {
var url = config.urls.s3_airports_base_url + '/' + faa + '/' + t;
}
tempJson["sectionId"] = t;
tempJson["page"] = data[t];
httpRequests.makeHeadRequestWithCallerId(url, function (err, metax) {
if (metax) {
let z = metax.split('|')[0];
tempJson["SummaryRange"] = getSummaryRangeAirportPageList(z);
tempJson["timestamp"] = new Date(parseInt(z)).toLocaleDateString();
tempJson["callerId"] = metax.split('|')[1];
} else {
tempJson["timestamp"] = '';
tempJson["callerId"] = '';
tempJson["SummaryRange"] = '';
}
result.push(tempJson);
i++;
if(count === i){
logger.info("Final result: ", result);
callback(null, result);
}
})
});
}

Synchronous api calls in Node.js

I've a cronjob that runs every 10 secs. It requests for machines for a single client and does computation based on the response and then has to update or create documents with those computations in a for loop. But, the api calls after '***' in the code don't happen until the for loop has executed and the data sent to the api calls is that of the last machine which is wrong. I want to solve this by this way or some other way possible. My code looks like this:
// index.js
const cron = require("node-cron");
const express = require("express");
const fs = require("fs");
const request = require("request");
app = express();
var clientId = 'ABCD';
var apiUrl = 'http://example.com:3001/';
var getMachines = apiUrl + 'getMachines/',
updateMachine = apiUrl + 'updateMachine/',
getControlRoomStatus = apiUrl + 'getControlRoomStatus/',
registerControlRoomStatus = apiUrl + 'registerControlRoomStatus/',
updateControlRoomStatus = apiUrl + 'updateControlRoomStatus/';
cron.schedule("*/10 * * * * *", function() {
APICall(getMachines, { 'clientId' : clientId }, 'POST', function(err, machines) {
if (err) {
console.log(err);
} else {
console.log('--------------------------------------------------------------------------------------------------');
var allMachines = machines;
var currentDateTime = IST();
for (var i = 0; i < 2; i++) {
var lastCycleTime = new Date(allMachines[i]['lastCycleTime']);
var lastHeartbeat = new Date(allMachines[i]['lastHeartbeat']);
var machineData;
var controlRoomData;
var machineId = {
'machineId' : allMachines[i]['machineId']
};
console.log(machineId);
if (allMachines[i]['downtimeStatus'] == '0') {
if ((currentDateTime - lastCycleTime)>300000) {
if ((currentDateTime - lastHeartbeat)>300000) {
console.log(allMachines[i]['machineId'] ,' No Internet');
controlRoomData = {
'clientId': clientId,
'lastTimeStamp': allMachines[i]['lastCycleTime'],
'status': 'Inactive',
'type': 'No Internet/Power'
};
} else {
console.log(allMachines[i]['machineId'] ,' No button pressed');
controlRoomData = {
'clientId': clientId,
'lastTimeStamp': allMachines[i]['lastCycleTime'],
'status': 'Inactive',
'type': 'No Button Pressed'
};
}
machineData = {
'status' : 'Inactive'
};
} else {
console.log(allMachines[i]['machineId'] ,' Active');
machineData = {
'status' : 'Active'
};
controlRoomData = {
'clientId': clientId,
'lastTimeStamp': allMachines[i]['lastCycleTime'],
'status': 'Active',
'type': 'N.A'
};
}
} else {
if ((currentDateTime - lastHeartbeat)>300000) {
console.log(allMachines[i]['machineId'] ,' button pressed ',' No Internet');
controlRoomData = {
'clientId': clientId,
'lastTimeStamp': allMachines[i]['lastCycleTime'],
'status': 'Inactive',
'type': 'No Internet/Power'
};
} else {
var downtimeLength = allMachines[i]['downtimeData'].length - 1;
console.log(allMachines[i]['machineId'] ,' button pressed ',allMachines[i]['downtimeData'][downtimeLength]['downtimeType']);
controlRoomData = {
'clientId': clientId,
'lastTimeStamp': allMachines[i]['lastCycleTime'],
'status': 'Inactive',
'type': allMachines[i]['downtimeData'][downtimeLength]['downtimeType']
};
}
machineData = {
'status' : 'Inactive'
};
}
***
APICall(getControlRoomStatus, machineId, 'POST', function(err, controlRoom) {
if (err) {
console.log(err);
} else {
console.log(machineId,controlRoomData);
if (controlRoom == null ) {
APICall(registerControlRoomStatus, controlRoomData, 'POST', function(err, body) {
if (err) {
console.log(err);
} else {
// console.log(body);
}
});
} else {
var updateControlRooomUrl = (updateControlRoomStatus+''+controlRoom['_id']+'');
// console.log(updateControlRooomUrl);
APICall(updateControlRooomUrl, controlRoomData, 'PUT', function(err, body) {
if (err) {
console.log(err);
} else {
// console.log(body);
}
});
}
}
});
var updateMachineUrl = (updateMachine+''+allMachines[i]['_id']+'');
// console.log(updateMachineUrl);
APICall(updateMachineUrl, machineData, 'PUT', function(err, body) {
if (err) {
console.log(err);
} else {
console.log(i,machineId);
// console.log(body);
}
});
}
}
});
});
function APICall(url, requestData, method, callback) {
request({
url: url,
form: requestData,
method: method
}, function (error, response, body) {
if (error || response.statusCode !== 200) {
return callback(error || {statusCode: response.statusCode});
}
callback(null, JSON.parse(body));
});
}
function IST(){
var dateUTC = new Date();
var dateUTC = dateUTC.getTime();
var dateIST = new Date(dateUTC);
dateIST.setHours(dateIST.getHours() + 5);
dateIST.setMinutes(dateIST.getMinutes() + 30);
return dateIST;
}
app.listen(3128);
Thank you in advance.
I used a different method to do things and now it's working just as it's supposed to. I used 'async' and replaced the for loop with the following:
var async = require('async');
...
async.map(allMachines , function(machine, callback) {
...
});
...
You can try the following package:
sync-request
You can find it here on NPM.
Here is an example how to use it (from the docs):
var request = require('sync-request');
var res = request('GET', 'http://example.com');
console.log(res.getBody());
As stated in the documentation, don't use it in production code, since this will terribly block your server and it will slow down considerably (if you are running a HTTP server which you are using express).
If you have asynchronous code and you want to execute some code after the asynchronous you also can use:
Observables (not native need to use a package, RxJS for example)
Promises (native ES6 JS)

Fail to pass result in request-promise

I would like to call an API that helped to extract some data from Facebook. I expect the API will keep looping itself on or before a specified date. If an expected result is found, then it should return a json. But the code below, it always returns an empty json.
app.get('/fb/test', (req, res) => {
const options = {
method: 'GET',
uri: 'https://graph.facebook.com/v2.10/me/tagged_places',
qs: {
access_token: token,
limit: 10,
fields: 'created_time,id,place'
}
};
request(options)
.then(fbRes => {
var found = false;
loop(fbRes);
function loop(returnData){
const parsedRes = JSON.parse(returnData).data;
var start = moment.tz("2010-06-01 00:00", timezone).format();
for (var i = 0; i < parsedRes.length; i++) {
var date = moment.tz(parsedRes[i].created_time, timezone).format();
if( date >= start ){
console.log(parsedRes[i].place.name);
if(parsedRes[i].place.name == "Moscow, Russia"){
found = true;
res.json({ result: true });
break;
}else if(i==parsedRes.length-1 && found == false){
let newOptions = {
method: 'GET',
uri: JSON.parse(returnData).paging.next
};
request(newOptions)
.then(newData => {
loop(newData);
})
.catch(function (err) {});
return ture;
}else{
//break;
}
}else{
res.json({ result: false });
}
}
}
})
.catch(function (err) {
res.json(err);
});
});

Custom code parsing issue- Request Entity Too Large - Oracle MCS

Hi I am facing an issue while accessing custom api using Oracle MCS
{
"message": "Custom Code Problem parsing JSON: request entity too large"
}
This occur while calling an api with request containing a byte array of an image.
my code given below
service.post('/mobile/custom/meraasmcs/documentofrecords/updateemiratesid',function(req,res){
console.info("Request Before Api call=>"+req);
var connector = '/documentofrecords/updateemiratesid'
commonHandler.CommonHandlerPostMethodFunction(
req,res,connector)
commonHandler.js
module.exports = {
CommonHandlerPostMethodFunction:
function (req, res, connector) {
/*
* Description : This function handles all the request and response
* Output : Returns a json content success message
* Author : Anand Raj
* Created Date : 10/10/2016
*/
var app = express();
var newReqBody=app.use(bodyParser.json({limit: '50mb'}));
console.info('New ReqBody=>'+newReqBody);
var errorMsg;
var finalResponse;
var headerIndex = JSON.stringify(
req.headers).search('application/json');
var versionNumberIndex = JSON.stringify(
req.headers).search('x-api-version');
var reqBody = JSON.stringify(req.body);
console.info('header ' + JSON.stringify(req.headers));
console.info('version index ' + versionNumberIndex);
console.info('version number ' + req.headers['x-api-version']);
console.info('Req body ' + reqBody);
res.header('Access-Control-Allow-Origin','*'); // To overcome cross origin issue in Windows platform
if (0 > headerIndex) {
finalResponse = jbuilder.encode(function (json) {
json.set('Response', function (json) {
json.set('responseCode', '415');
json.set('responseMessage', 'Unsupported media-type');
});
});
res.status(415).send(finalResponse);
res.end();
} else if (reqBody === '{}') {
finalResponse = jbuilder.encode(function (json) {
json.set('Response', function (json) {
json.set('responseCode', '400');
json.set('responseMessage', 'Malformed request body');
});
});
res.status(400).send(finalResponse);
res.end();
} else if (0 > versionNumberIndex) {
finalResponse = jbuilder.encode(function (json) {
json.set('Response', function (json) {
json.set('responseCode', '400');
json.set('responseMessage', 'Version Number missing');
});
});
res.status(400).send(finalResponse);
res.end();
} else {
/* request part */
var versionNumber = req.headers['x-api-version'];
var optionsList = {
uri: '/mobile/connector/MeraasAllConnector'+connector,
body: reqBody,
headers: {
'Content-Type': 'application/json',
'X-API-Version': versionNumber
}
};
/* handler part */
var handler = function (error, response, body) {
if (error) {
if ('message' in error) {
errorMsg = error.message;
//res.send(500, errorMsg);
//res.end();
finalResponse = jbuilder.encode(function (json) {
json.set('Response', function (json) {
json.set('responseCode', '500');
json.set('responseMessage', errorMsg);
});
});
res.status(500).send(finalResponse);
res.end();
} else {
finalResponse = jbuilder.encode(function (json) {
json.set('Response', function (json) {
json.set('responseCode', '408');
json.set('responseMessage', 'Response Timed Out');
});
});
res.status(408).send(finalResponse);
res.end();
}
} else {
if (response.statusCode !== 200) {
finalResponse = jbuilder.encode(function (json) {
json.set('Response', function (json) {
json.set('responseCode', response.statusCode);
json.set('responseMessage', response.message);
});
});
res.status(response.statusCode).send(finalResponse);
res.end();
} else if(response.statusCode==401){
finalResponse = jbuilder.encode(function (json) {
json.set('Response', function (json) {
json.set('responseCode', '401');
json.set('responseMessage', 'Authorization Required.');
});
});
res.status(401).send(finalResponse);
res.end();
}
else {
res.status(200).send(body);
res.end();
}
}
};
req.oracleMobile.rest.post(optionsList, handler);
}
}
};
Package.json
{
"name" : "meraasmcs",
"version" : "1.47.0",
"description" : "Contains all the custom Apis for Meraas Mobile App",
"main" : "meraasmcs.js",
"dependencies":
{
"jbuilder":"0.0.4",
"body-parser":"1.15.2",
"express":"4.14.0"
},
"oracleMobile" : {
"dependencies" : {
"apis" : { },
"connectors" : {"/mobile/connector/MeraasAllConnector":"1.0"}
}
}
}
If i reduce the size of image then pass its corresponding byte array, then there response will be success.
I checked related questions, all it says
var bodyParser = require('body-parser');
app.use(bodyParser.json({limit: '50mb'}));
app.use(bodyParser.urlencoded({limit: '50mb', extended: true}));
But i tried that also. Could anyone please help me??
Sample Request
{
"P_PERSON_ID": 31441,
"P_LOGIN_PERSON_ID": 31441,
"TIME_STAMP": null,
"P_EMIRATES_ID_TAB": [{
"DocumentExtraInfoId": "",
"ValidFrom": "2016-11-23",
"ValidTo": "2016-11-24",
"CardNumber": "Ggv4"
}],
"P_ATTACHMENT_TAB": [{
"Title": "image.jpg",
"DocumentId": null,
"DeleteFlag": "N",
"Description": "Testqwe",
"AttachmentName": "Test",
"FileData": "",
"AttachmentType": "image/jpeg"
}]
}
Issue comes when the length of the value of FileData is too large.
Thanks in advance

Resources