Sending response to client from within the request.post callback in koa - node.js

I have this koa route /landing which is resulting in 404.
function* landing() {
//this.body = "response"; //1
var request = require('request');
request.post('http://url.com/resource',
{ json: { key: "post data"} },
function (error, response, body) {
if (!error && response.statusCode == 200) {
var token = body.data;
getListByToken(token, function(list){
this.body = list; //2
});
}
});
}
See comment in the top //1 - that is how you define body of a response in koa in a route. Instead of //1 I want to send response from //2 i.e. from within that request.get.
When a user is routed to /landing a post request has to fetch some data from a url. That fetched data is to be used by getListByToken to bring some other data, list, which should be sent to the user. The above code should have worked but it results in 404 Not Found response by koa.

We can use promises, simple and clean way of managing asynchronous codes.
var request = require('request-promise');
. . .
function* landing() {
try {
let response = yield request( {
method: 'POST',,
url: 'http://url.com/resource',
headers: { 'content-type': 'application/json' },
body: JSON.stringify( { json: { key: "post data"} } )
} );
this.body = yield new Promise( function( resolve, reject ) {
if ( response.statusCode == 200 ) {
getListByToken( response.body.token, function( list ) {
resolve( list );
} );
}
} );
} catch ( err ) {
/* do something with your errors */
}
}

Solved it with q. It makes koa hold response until yield happens.
var q = require('q');
function* landing() {
var deferred = q.defer();
var request = require('request');
request.post('http://url.com/resource',
{ json: { key: "post data"} },
function (error, response, body) {
if (!error && response.statusCode == 200) {
var token = body.data;
getListByToken(token, function(list){
deferred.resolve(repolist);
});
}
});
this.body = yield deferred.promise;
}
Thanks to https://stackoverflow.com/a/22159513/1128379

Related

How to call rest api in express js

I am new in nodejs and I am using express js, I am calling REST API and want to show the response, but my problem is that the response is showing in console.log but I want to pass the body(response) in assistant.ask, where I am wrong here is my code:
var request = require('request');
let rawInput = function (assistant) {
let rawInput = assistant.getRawInput();
request.post(
'http://xxxxxxx.ngrok.io/api/v1/240/respond',
{ json: { query: rawInput } },
function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body);
assistant.ask(body);
}
else{
console.log(error);
}
}
);

How to use the values of a POST response in Node.js?

I am setting up an API connection via Node.js. I had some predefined cURL code which I converted into Node.js code, which I have provided below. Until now everything works fine, I am displaying the value I need (token) inside the console window.
However, I am wondering how I can use this token variable in another function? So I somehow have to save it as a global variable, but until now that didn't work.
var request = require('request');
var headers = {
'content-type': 'application/x-www-form-urlencoded',
'Authorization': 'XXXXXXXXXXXXXXXXX'
};
var dataString = 'grant_type=client_credentials';
var options = {
url: 'XXXXXXXXXXXXXXXX',
method: 'POST',
headers: headers,
body: dataString
};
function callback(error, response, body) {
if (!error && response.statusCode == 200) {
var str = body;
token = str.split('\"')[3];
console.log(token);
}
}
request(options, callback);
You can access token only when request() complete and calls the callback function. This is due to the non-blocking nature of node.js - when you start a request the code doesn't block and you can access its response only when it completes and call the callback function. Hence you first define the callback function and pass it to request as an argument. If you want to access token you can create another function and call it inside the callback.
var request = require('request');
var headers = ...
var dataString = ...
var options = ...
function doStuffWithToken(token) {
console.log(token)
}
function callback(error, response, body) {
if (!error && response.statusCode == 200) {
var str = body;
token = str.split('\"')[3];
doStuffWithToken(token);
}
}
request(options, callback);
You can also use promises for better code:
var request = require('request');
function getToken() {
var headers = ...
var dataString = ...
var options = ...
return new Promise((resolve, reject) => {
request(options, (error, response, body) => {
if (error) return reject(error)
if (response.statusCode == 200) {
var str = body;
token = str.split('\"')[3];
resolve(token);
}
}
}
}
getToken()
.then((token) => {
// here you can access the token
console.log(token)
})
.catch((error) => {
console.error('unable to retrieve token', error)
})
Here we create a wrapper around our request. getToken() returns a promise object that you can use to register two handlers for when it resolves successfully and for when it rejects and throw an error.
You can use getToken() also with the await/async keyword
var request = require('request');
function getToken() {
var headers = ...
var dataString = ...
var options = ...
return new Promise((resolve, reject) => {
request(options, (error, response, body) => {
if (error) return reject(error)
if (response.statusCode == 200) {
var str = body;
token = str.split('\"')[3];
resolve(token);
}
}
}
}
async function main() {
let token = await getToken()
console.log(token)
}
main()
.then(...)
.catch(...)
Further readings:
Don't block the event loop

multiple serialise call in rxjx on server side using Request module

I have to make multiple serialise call on server side in NodeJs using request module , and RxJs Observable
I have array of Url Address like ['www.google.com','facebook.com']
When I make request to call then server get busy in event loop . I want to know when my last url call gets response so that I can send response to front end
here is my code so far
const foo = Observable.create(function (observer) {
res.writeHeader(200, { "Content-Type": "text/html" });
var str = '<html><head></head><body><h1> Following are the responses: </h1><ul>'
res.write(str);
let count = 0;
addressesArray.forEach(function (element, i) {
observer.next(element);
if (some Condition) {
console.log('here i want to call complete when I get last response')
// observer.complete();
}
})
})
and this is my subscribe function
const subscription = foo.subscribe({
next : addres =>
{
request(addres , function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(response)
}
if (typeof response === "undefined" || typeof body === "undefined") {
console.log('No resp')
}
})
},
complete:()=>{console.log('done')}
})
You can start off your Observable from addressesArray with from operator, it'll complete itself when it reach the end of the array
from(addressesArray).pipe(
mergeMap(address => {
return new Observable(obs => {
request(address, function (error, response, body) {
if (!error && response.statusCode == 200)
obs.next(response)
else
obs.next('')
obs.complete()
})
})
}),
reduce((allResponses, response) => {
return allResponse += '<li>' + response + '<li/>'
}, ''),
tap(allResponses => {
res.writeHeader(200, { "Content-Type": "text/html" });
var str = '<html><head></head><body><h1> Following are the responses: </h1><ul>'
res.write(allResponses + '</ul')
res.end()
})
).subscribe()

node.js sending by request module

I need to send a lot of messages. I use external api and request module:
email.js
var request = require('request');
module.exports = function(subject, email){
var message = ... ;
var options = {
method: 'POST',
url: 'https://api.emails.net.com/api/sendmail',
form: {
smtp_account: smtp,
to: {},
subject: subject,
html: message,
from: 'myapp#email.com',
from_name: 'Myapp'
},
headers: {
'Authorization': ' ... '
}
};
request(options, function (error, response) {
if (!error && response.statusCode === 200) return true;
return false;
});
};
And in another place:
var sendEmail = require('../email');
...
for( ... ){
if(sendEmail(subject, email)){
//do something
}
}
After success i want to do something but request return nothing. Is any way to check if post was success and do something in place where I require email module? I'm sending emails in loop and i must check one by one.
You can do something like this
var request = require('request');
var Promise = require('bluebird');
var email = function () {
return {
send: function (subject, email) {
var message = "test";
var options = {
method: 'POST',
url: 'https://api.emails.net.com/api/sendmail',
form: {
smtp_account: "smtp",
to: {},
subject: subject,
html: message,
from: 'myapp#email.com',
from_name: 'Myapp'
},
headers: {
'Authorization': ""
}
};
return new Promise(function (resolve, reject) {
request(options, function (error, response) {
if (!error && response.statusCode === 200) {
resolve(true);
} else {
reject(err);
}
});
})
}
}
};
module.exports = email();
And then you can consume this as below
for (var i = 0; i < 10; i++) {
console.log(i);
email
.send("test", "test#gmail.com")
.then(function (status) {
///Do what ever u want to do
})
.catch(function (err) {
console.log(err);
});
}

Node.js request inside express server doesn't seem to work in parallel

I've a simple express server responding to one post request:
app.post('/reportFiles', getReportLink);
The server is going to make a post request on another server then save the result into a json file.
But it seems to be not working when i make multiple request. If I call 2 times my express server and the request to the other server are slow, I'll get the result of my first request but never my second (request are the same, just called 2 times).
Here is my code for the function getReportLink:
function getReportLink(req,res){
var params = req.body;
// Send 200 response -> Doing the job in background
respond(res,200,'OK');
var json;
var requestName = params.requestName;
var sessionId = params.sessionId;
var startDate = params.startDate;
var endDate = params.endDate;
var customerId = params.customerId;
var uaid = params.uaid;
var jsonFileName = requestName+'_'+customerId+'_'+uaid+'_'+unix()+'.json';
var platformUrl = require(current_path+path.sep+'platform').getPlatformUrl(config.environment);
async.series([
// Call getrequestName on spring-ws
function(callback){
var requestBody = {sessionId:sessionId,asynch:false,startDate:startDate,endDate:endDate,formatedForTimezone:true,timeZoneOffset:timeZoneOffset};
var reportParams = params;
_.each(_.keys(reportParams), function (key) {
if(key==='reportType' && reportParams[key]<=0){
// We don't add it
}else{
requestBody[key] = reportParams[key];
}
});
logger.debug(jsonFileName);
logger.debug(requestBody);
request({
uri: platformUrl+'get'+reportParams.requestName,
method: 'POST',
json: true,
timeout: 600000,
headers: {'content-type': 'application/json'},
body: requestBody},
function(error, response, body) {
if(!_.isUndefined(response)){
logger.debug(jsonFileName);
logger.debug('Response: '+ response.statusCode);
}
if (error || response.statusCode == 500) {
logger.debug(jsonFileName);
logger.error(error);
logger.debug('Received:'+JSON.stringify(body));
if(!_.isUndefined(returnUrl) && returnUrl){
return respond(res,500, 'Error when getting ressource');
} else {
return logger.error('Error when getting ressource');
}
} else {
json = body;
if( _.isUndefined(json) || _.isNull(json)){
logger.debug(jsonFileName);
logger.debug('Received:'+JSON.stringify(json));
if(!_.isUndefined(returnUrl) && returnUrl){
return respond(res,500, 'Error when getting ressource - not a json object');
} else {
return logger.error('Error when getting ressource - not a json object');
}
} else {
logger.debug(jsonFileName+' : '+' OK go to next');
callback(null, 'getReportName');
}
}
});
},
// Save Json on filesystem
function(callback){
logger.debug(jsonFileName+' : '+' Saving on disk');
if(_.isUndefined(json)){
logger.error('Json is undefined...');
}
fs.writeFile(jsonFileName, JSON.stringify(json), 'utf8', function (err) {
if (err) return logger.error(params);
callback(null, 'writeJson');
});
}
]);
}
Solved this using node-fetch.
Code instead of request now looks like this:
fetch(uri, { method: 'POST', body: JSON.stringify(requestBody), timeout: 600000, headers: {'content-type': 'application/json'} })
.then(function(response) {
logger.debug('Response: '+ response.status + ' ok?'+response.ok);
if (!response.ok) {
logger.debug('Received: '+response.statusText);
return respond(res,500, 'Error when getting ressource. Status='+response.status);
} else{
json = response.json();
if( _.isUndefined(json) || _.isNull(json)){
return respond(res,500, 'Error when getting ressource');
} else {
callback(null, 'getReportName');
}
}
});

Resources