Postpone responding to request in Node.js - node.js

When my Node.js Express server, which is listening on port 3000, receives a request, it routes to a function that must issue a POST to another Web site and get the response before responding to the initial request.
Is that possible?
Here is the code I'm using:
app.get('/silence/:host', routes.silence);
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
exports.silence = function(request, response){
var hostname = utils.validateHost(request);
if (stash.createSilencer(hostname)) {
response.writeHead(200, {"Content-Type": "application/json"});
response.write('{ "success" : true, "message" : "Successfully silenced host'" }');
response.end();
}
}
exports.createSilencer = function(hostname) {
var options = {
url: 'http://x.x.com:4567/create/silencer/' + hostname ,
method: 'POST',
body: '{ "timestamp": ' + utils.timestamp() + '} '
};
request(options, silencer_callback);
##### DONT WANT TO RETURN UNTIL THE silencer_callback IS INVOKED
return true;
}
function silencer_callback(error, response, body) {
if (!error && response.statusCode == 200) {
var info = JSON.parse(body);
console.log("Response Recieved");
}
}

The trick is that you don't call response.write() and response.end() until you receive a response from you POST request. You just exit the method without sending response back. Once you have result from your POST request, you can finish initial response.
exports.silence = function(req, res){
var hostname = utils.validateHost(req);
stash.createSilencer(hostname, function(error, response, body) {
if (!error && response.statusCode == 200) {
var info = JSON.parse(body);
console.log("Response Received");
}
// we get POST-response, lets response to initial request here
res.writeHead(200, {"Content-Type": "application/json"});
res.write('{ "success" : !error, "message" : "Successfully silenced host'" }');
res.end();
});
// return from the function, but do not send response back yet
}
exports.createSilencer = function(hostname, callback) {
var options = {
url: 'http://x.x.com:4567/create/silencer/' + hostname ,
method: 'POST',
body: '{ "timestamp": ' + utils.timestamp() + '} '
};
request(options, callback);
// return from the function, but do not send response back yet
}

Related

How can I send my username and password to a server when requesting it for some data?

I want to retrieve some data from a server and when I visit the server's site, I am prompted for my username and password like in the image attached.
I want to write some code that will do this for me. However, I have not found a solution that works.
I've tried the request and node-fetch modules with no success.
var url = 'http://' + username + ':' + password + '#some.server.com/data';
request({url: url}, function (error, response, body) {
console.log('error:', error); // Print the error if one occurred
console.log('statusCode:', response && response.statusCode); // Print the
response status code if a response was received
console.log('body:', body); // Print the HTML for the Google homepage.
});
var auth = "Basic " + new Buffer(username + ":" + password).toString("base64");
request(
{
url : url,
headers : {
"Authorization" : auth,
'sendImmediately': false
}
},
function (error, response, body) {
// Do more stuff with 'body' here
console.log('error:', error); // Print the error if one occurred
console.log('statusCode:', response && response.statusCode); // Print the response status code if a response was received
console.log('body:', body); // Print the HTML
}
);
fetch('some.server.com/data',
{
method: 'GET',
credentials: 'same-origin',
redirect: 'follow',
agent: null,
headers: {
'Authorization': auth,
},
timeout: 5000
})
.then(function(response){
return response.text();
})
.then(function(text){
console.log('Request success: ' + text);
})
.catch(function(error) {
console.log('Request error: ' + error);
});
How can I insert the username and password within the code so that the data retrieval process is automated? Can anyone guide me in the right direction?
Thanks.
If you're sure you're using Basic Auth then try this
request(
{
url : url,
auth: { <============ This
user: username,
password: password
}
},
function (error, response, body) {
// Do more stuff with 'body' here
console.log('error:', error); // Print the error if one occurred
console.log('statusCode:', response && response.statusCode); // Print the response status code if a response was received
console.log('body:', body); // Print the HTML
}
);

Connect https using nodejs

I am trying to maintain some old Node js code. I am having trouble in connecting to https url using corporate proxy.
Below code doesn't seem to work.
var https = require('https');
var options = {
hostname: 'PROXY_IP',
port : PROXY_PORT,
path : 'https://server.ourdomain.com/path/to/secure/api',
rejectUnauthorized : false,
headers: {
'Authorization': 'Basic ' + new Buffer('username:password').toString('base64'),
'Content-Type': 'application/json',
'Host' : 'https://server.ourdomain.com:443'
}
}
var responseChunk = '';
callback = function(response) {
if(response.statusCode !== 200) {
//Error occured. Handle error
}
response.on('data', function (chunk) {
responseChunk += chunk;
});
response.on('end', function () {
// Got complete response. Process and do something
});
}
var get_req = https.request(options, callback);
get_req.on('error', function(e) {
console.log("Error:" + e)
});
get_req.end();
Error after executing this is
Error:Error: socket hang up
I was able to get this working using request module. But not using https module.
What seems to be the problem?
Use request..
var request = require('request');
request({'url':'https://anysite.you.want/sub/sub','proxy':'http://yourproxy:8087'}, function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body);
}
})

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');
}
}
});

Slack no payload received nodejs

SO using curl I can successfully send post request to slack
curl -X POST --data-urlencode 'payload={"channel": "#tech-experiment", "username": "at-bot", "text": "This is posted to #general and comes from a bot named webhookbot.", "icon_emoji": ":ghost:"}' https:/company.slack.com/services/hooks/incoming-webhook?token=dddddddd2342343
however when I converted it to code using nodejs
var request = require('request');
var http = require('http');
var server = http.createServer(function(req, response){
response.writeHead(200,{"Content-Type":"text/plain"});
response.end("end");
});
option = {
url: 'https://company.slack.com/services/hooks/incoming-webhook?token=13123213asdfda',
payload: '{"text": "This is a line of text in a channel.\nAnd this is another line of text."}'
}
request.post(
option,
function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body)
}else {
console.log('wtf')
console.log(response.statusCode)
console.log(response)
console.log(error)
}
}
);
it throws status 500. can anyone help?
i reviewed the token
also done my research but nothing is working..
I appreciate all your help
You need to use the https library, since the server requests are on a different port. You current code is sending the request to port 80 instead of port 443. This is some sample code I built for an integration.
var https = require( 'https' );
var options = {
hostname : 'company.slack.com' ,
path : '/services/hooks/incoming-webhook?token=rUSX9IyyYiQmotgimcMr4uK8' ,
method : 'POST'
};
var payload1 = {
"channel" : "test" ,
"username" : "masterbot" ,
"text" : "Testing the Slack API!" ,
"icon_emoji" : ":ghost:"
};
var req = https.request( options , function (res , b , c) {
res.setEncoding( 'utf8' );
res.on( 'data' , function (chunk) {
} );
} );
req.on( 'error' , function (e) {
console.log( 'problem with request: ' + e.message );
} );
req.write( JSON.stringify( payload1 ) );
req.end();
I think it is not payload but form.
This code succeed in calling Incoming Webhooks.
var request = require('request');
var options = {
uri: "https://hooks.slack.com/services/yourURI",
form: '{"text": "This code..."}'
};
request.post(options, function(error, response, body){
if (!error && response.statusCode == 200) {
console.log(body.name);
} else {
console.log('error: '+ response.statusCode + body);
}
});
wanted to chime in, as I found this while also trying to do the same thing. I ended up doing this:
got('https://hooks.slack.com/services/[your configured url]', {
method: 'POST',
body: JSON.stringify({
"text": "message" + variable
})
});
Either use form in your option object or set a body parameter along with the 'content-type' set to 'application/x-www-form-urlencoded'. Here's a working example.
var payload = JSON.stringify(payload)
request.post({
headers: {'content-type' : 'application/x-www-form-urlencoded'},
url: 'Your Webhook URL',
body: "payload="+payload
}, function(error, response, body){
if(error){
console.log(error);
}
console.log(body);
});

How to do request HTTP Digest auth with Node.JS?

I have to write some code with Node.JS for an API documentation, but I tried the last few days all the solutions I could found on the web (including Stack of course) without succes...
My API use HTTP Digest Auth and that's the problem, I was able to connect, that's was not a big deal but everytime I got the same return :
Got response : 401
HTTP Digest Authentication required for "api.example.com"
You can show my base code below without auth! Because I don't know what I can do after all the try I did :
var http = require('http')
var options = {
host: 'api.example.com',
path: '/example/1.xml',
};
var request = http.get(options, function(res){
var body = "";
res.on('data', function(data){
body += data;
})
res.on('end', function(){
console.log('Got response : ' + res.statusCode);
console.log(body);
})
res.on('error', function(e){
console.log('Got error : ' +e.message);
});
});
One of my last try was to use this module https://npmjs.org/package/request but he doesn't work too as everytime I got 401 !
For more information I was able to connect and GET the information I needed from my API with Ruby, Python, php, and Java so I'm sure my API is working well and the information I pass are correct.
I use the last stable of Node v0.10.11 !
If someone can help me or have a solution up to date i will be glad.
EDIT :
I will add some details about my test with the module Mickael/request
First Try :
var request = require('request')
var options = {
'url': 'http://api.example.fr/example/1.xml',
'auth': {
'user': 'test',
'pass': 'test',
'sendImmediately': false
}
};
var request = request.get(options, function(error, response, body){
if (!error && response.statusCode == 200){
console.log('body : ' + body)
}
else{
console.log('Code : ' + response.statusCode)
console.log('error : ' + error)
console.log('body : ' + body)
}
});
Second Try :
var request = require('request')
request.get('http://api.example.fr/example/1.xml', function(error, response, body){
if (!error && response.statusCode == 200){
console.log('body : ' + body)
}
else{
console.log('Code : ' + response.statusCode)
console.log('error : ' + error)
console.log('body : ' + body)
}
}).auth('test', 'test', false);
but the return is still the same 401
Here's your example corrected to use request as per it's API.
var options = {
uri: 'http://api.example.fr/example/1.xml',
auth: {
user: 'test',
pass: 'test',
sendImmediately: false
}
};
request(options, function(error, response, body){
if (!error && response.statusCode == 200){
console.log('body : ' + body)
}
else{
console.log('Code : ' + response.statusCode)
console.log('error : ' + error)
console.log('body : ' + body)
}
});
The request chainable style API is a bit confusing (IMHO), but I believe you can make it work that way as well.
The digest auth in the request package seems to be incomplete.
You can try out: https://npmjs.org/package/http-digest-client ,its a pretty decent lightweight implementation for the digest authentication.
If you need to do a digest auth POST with a body message to be sent you can use request in conjunction with http-digest-client. After installing both just open up http-digest-client code under node-modules and replace its use of the http package with the request package api.
Try urllib it will work with simple and disgest auth.
const httpClient = require('urllib');
const url = 'https://site.domain.com/xmlapi/xmlapi';
const options = {
method: 'POST',
rejectUnauthorized: false,
// auth: "username:password" use it if you want simple auth
digestAuth: "username:password",
content: "Hello world. Data can be json or xml.",
headers: {
//'Content-Type': 'application/xml' use it if payload is xml
//'Content-Type': 'application/json' use it if payload is json
'Content-Type': 'application/text'
}
};
const responseHandler = (err, data, res) => {
if (err) {
console.log(err);
}
console.log(res.statusCode);
console.log(res.headers);
console.log(data.toString('utf8'));
}
httpClient.request(url, options, responseHandler);
your sample is work
var request = require('request')
request.get('http://api.example.fr/example/1.xml', function(error, response, body){
if (!error && response.statusCode == 200){
console.log('body : ' + body)
}
else{
console.log('Code : ' + response.statusCode)
console.log('error : ' + error)
console.log('body : ' + body)
}
}).auth('test', 'test', false);

Resources