Node.js sending http request in a loop - javascript

I'm actually facing a problem with my javascript code executed with node.js
i need to send http requests in a loop to a distant server (i set www.google.ca in the code).
Here is my code :
var http = require('http');
var options = {
hostname: 'www.google.ca',
port: 80,
path: '/',
method: 'GET'
};
function sendRequest(options){
console.log('hello');
var start = new Date();
var req = http.request(options,function(res) {
console.log('Request took:', new Date() - start, 'ms');
});
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
req.end();
};
for(var i=0;i<10;i++){
sendRequest(options);
}
The problem I have is that, no matter how many times i go through my loop, i get a response for only the 5 first of them. For the rest of the requests, the function sendRequest() is called but I don't get any responses, neither error message. And then the program terminates.
However it works fine when I set localhost as a host.
Is anyone would have a solution to this problem ?
Thanks in advance !

perhaps either your machine or the remote machine is getting overwhelmed by the 10 simultaneous requests you make. try sending them one at a time, you will have to wait until the first request completes before continuing. one easy way to do so is with async.timesSeries
var http = require('http');
var async = require('async');
var options = {
hostname: 'www.google.ca',
port: 80,
path: '/',
method: 'GET'
};
function sendRequestWrapper(n, done){
console.log('Calling sendRequest', n);
sendRequest(options, function(err){
done(err);
});
};
function sendRequest(options, callback){
//console.log('hello');
var start = new Date();
var req = http.request(options,function(res) {
// I don't know if this callback is called for error responses
// I have only used the `request` library which slightly simplifies this
// Under some circumstances you can accidentally cause problems by calling
// your callback function more than once (e.g. both here and on('error')
console.log('Request took:', new Date() - start, 'ms');
callback(null);
});
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
callback(err);
});
req.end();
};
async.timesSeries(10, sendRequestWrapper);

Related

Ajax get request not getting response after 5 calls

I'm trying to get some information from the mongodb server to the frontend with ajax get request. Everything works fine except that if i try to call 5 times the javascript function, i dont get any response from my local server.
I tried to put some console.log() in order to debug in the nodejs function, it appears that the 6th time i call the function, the nodejs function doesn't even run.
javascript ajax front end code :
function addLike(music){
var request = new XMLHttpRequest();
request.open('POST', '/AddLike', true);
request.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
var myobj = {"music": music};
request.send(JSON.stringify(myobj));
setTimeout(function(){
$.ajax({
url: "/getAll",
type: 'GET',
dataType: 'json', // added data type
success: function(res) {
// => the 6th time i launch addLike(music), the function doesn't go there
update(res);
}
});
}, 200);
}
nodejs function :
app.get("/getAll", function(req, res){
var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/";
MongoClient.connect(url, { useNewUrlParser: true }, function(err, db) {
if (err) throw err;
var dbo = db.db("SoundShare");
var tab = dbo.collection('Musique');
tab.find({}).toArray(function(err2, result) {
if (err2) throw err2;
res.send(JSON.stringify(result));
db.close();
});
});
});
As you can see on the image below, in the console of firefox the last get ajax request doesn't receive any response.
.
.
It seems like it is a server side problem but i don't understand how to fix it.
Thank you in advance for your answer.
Your problem is that you are creating a new connection inside your /getAll function and the default poolsize is 5 as you can see in the docs.
You should be creating the connection when your node.js app starts up and use that connection throughout the application instead of creating a new connection on each request.

Crash of website when making https (api) requests using sockets.io

We are facing some difficulties with a website we try to make. The website has a Javascript front end and backend. The backend uses socket.io for processing https requests through funnels. All works fine for now, but when we load test it, it slows down extremely. The site crashes before we can use it with 5 different devices. Eventually it shows an econn reset(see our error handler below).
//Doesn't stop server after crashing
process.on('uncaughtException', function (err) {
console.error(err.stack);
console.log("Node NOT Exiting...");
var datetime = new Date();
fs.appendFile('log.txt', "\n\r"+datetime+"\n\r"+err.stack, function (err) {
});
});
We also have some error handling code, but this code automatically kicks out all users of the server which results in displaying no results. We would want that this only shows up, for users who actually loose connection with the server (Hence not all other users).
See our code for making the https requests:
return new Promise(function(resolve,reject)
{
var options = {
host: hostUrl,
port: 443,
path: path,
method: method,
dataType: "json",
headers: {
accept: '*/*'
}
};
var req = https.request(options, function(res) {
var result = '';
res.on('data', function(chunk){
result += chunk;
});
res.on('end', function(){
//Only send result back when its in json format
if(!result || result.indexOf('application/json') !== 0)
{
// preserve newlines, etc - use valid JSON
result = result.replace(/\\n/g, "\\n")
.replace(/\\'/g, "\\'")
.replace(/\\"/g, '\\"')
.replace(/\\&/g, "\\&")
.replace(/\\r/g, "\\r")
.replace(/\\t/g, "\\t")
.replace(/\\b/g, "\\b")
.replace(/\\f/g, "\\f");
// remove non-printable and other non-valid JSON chars
result = result.replace(/[\u0000-\u0019]+/g,"");
resolve(exstractDataForNewTemplate(JSON.parse(result)); //Make sure the results fit in the same JSON with the addToTemplate function!
}
else
{
reject(null);
}
});
});
req.end();
req.on('error', function(e) {
console.error(e);
reject(null);
});
});
We would like to know how to solve this problem, either by improving the existing https request or by using an https request alternative. Suggestions are welcome.

What is the best way to determine Tomcat has started with node.js

I am building an application using node.js and that application communicates with a Tomcat server. While the tomcat server is launching, I am not sure if Tomcat is ready and has come up or not, for now I use CURL and WGET on Windows and Mac with a timeout of 2 seconds to keep checking if localhost:8080 has come up.
Is there a better way to do this without relying on CURL and WGET?
The suggested way is to create a heartbeat service on the tomcat application (I.E. a simple service that sends OK when it's up), and poll that every x seconds.
A heartbeat service is essential for monitoring while the application is running, and there are also times when the application isn't ready even though it's already listening on the port (because there is some heavy initialization going on).
There are other ways though, if you're on the same server, you can tail the catalina.out until you receive "server started" line.
You can setup your tomcat application to notify your server that it's up (though that means the tomcat needs to know the url for the node.js server), or alternatively setup some kind of message queue (like ApacheMq or such) that you can register when the tomcat is up, this will also allow push messages between the two services.
You could implement a httpWatcher (mimicking the contract of file watcher - fs.watch). It could poll an http endpoint (a status route or html file) and would fire a callback when a 200 is returned (or when a max runs has been reached). Something like this:
var request = require('request');
var watch = function(uri) {
var options;
var callback;
if ('object' == typeof arguments[1]) {
options = arguments[1];
callback = arguments[2];
} else {
options = {};
callback = arguments[1];
}
if (options.interval === undefined) options.interval = 2000;
if (options.maxRuns === undefined) options.maxRuns = 10;
var runCount = 0;
var intervalId = setInterval(function() {
runCount++;
if(runCount > options.maxRuns) {
clearInterval(intervalId);
callback(null, false);
}
request(uri, function (error, response, body) {
if (!error && response.statusCode == 200) {
clearInterval(intervalId);
callback(null, true);
}
});
}, options.interval);
}
Then use it like so:
watch('http://blah.asdfasdfasdfasdfasdfs.com/', function(err, isGood) {
if (!err) {
console.log(isGood);
}
});
Or pass in options...
watch('http://www.google.com/', {interval:1000,maxRuns:3},
function(err, isGood) {
if (!err) {
console.log(isGood);
}
});
Well, you can make requests from Node.JS app:
var http = require("http");
var options = {
host: "example.com",
port: 80,
path: "/foo.html"
};
http.get(options, function(resp){
var data = "";
resp.on("data", function(chunk){
data += chunk;
});
resp.on("end", function() {
console.log(data);
// do something with data
});
}).on("error", function(e){
// HANDLE ERRORS
console.log("Got error: " + e.message);
}).on("socket", function(socket) {
// ADD TIMEOUT
socket.setTimeout(2000);
socket.on("timeout", function() {
req.abort();
// or make the request one more time
});
});
Documentation:
http://nodejs.org/docs/v0.4.11/api/http.html#http.request

Node.js script would break when requesting HTTP responses from a site that does not exist

Using Node.js, when one requests a HTTP response, in optimal circumstances, the request comes back with a HTTP response.
However, sometimes the request breaks because the site, for example, has a 404 code, or the site does not exist at all. When requesting a batch of URLs, if there is a 404 code on, say, the 200th URL out of 1000 URLs requested, the entire script breaks. Here is my code:
var hostNames = ['www.gizmodo.com','www.sitethatdoesnotexist123.com','www.google.com'];
for (i; i < hostNames.length; i++){
var options = {
host: hostNames[i],
path: '/'
};
(function (i){
http.get(options, function(res) {
var obj = {};
obj.url = hostNames[i];
obj.statusCode = res.statusCode;
obj.headers = res.headers;
db.scrape.save(obj);
}).on('error',function(e){
console.log("Error Site: " + hostNames[i]);
});
})(i);
};
Is there a way, that for example, if the site does not exist, I simply skip to the next URL, instead of having the script break?
EDIT: Fixed. Thanks user DavidKemp
Use a try/catch block to catch any errors that might occur, and then continue on from there.
For example:
var hostNames = ['www.gizmodo.com','www.sitethatdoesnotexist123.com','www.google.com'];
//moved the function out so we do not have to keep redefining it:
var get_url = function (i){
http.get(options, function(res) {
var obj = {};
obj.url = hostNames[i];
obj.statusCode = res.statusCode;
obj.headers = res.headers;
console.log(JSON.stringify(obj, null, 4));
})
};
for (i; i < hostNames.length; i++){
var options = {
host: hostNames[i],
path: '/'
};
try {
get_url(i);
}
catch(err){
//do something with err
}
};
You need to bind an error handler to your request. I also cleaned up the code a bit.
hostNames.forEach(function(hostname), {
var req = http.get({host: hostName}, function(res) {
var obj = {
url: hostName,
statusCode: res.statusCode,
headers: res.headers
};
console.log(JSON.stringify(obj, null, 4));
});
req.on('error', function(err){
console.log('Failed to fetch', hostName);
});
});
You can use uncaughtException event. this let script run even after exception. link
process.on('uncaughtException', function(err) {
console.log('Caught exception: ' + err);
});
var hostNames = ['www.gizmodo.com','www.sitethatdoesnotexist123.com','www.google.com'];
for (i; i < hostNames.length; i++){
var options = {
host: hostNames[i],
path: '/'
};
(function (i){
http.get(options, function(res) {
var obj = {};
obj.url = hostNames[i];
obj.statusCode = res.statusCode;
obj.headers = res.headers;
db.scrape.save(obj);
}).on('error',function(e){
console.log("Error Site: " + hostNames[i]);
});
})(i);
};
Added a callback for when there's an error. Logs the site that returns an error on console. This error is usually triggered by a 404 or request time is too long.
The full docs are at http://nodejs.org/api/http.html#http_http_get_options_callback at the time of writing. loganfsmyth's answer provides a useful example.

Node.js http request

I am a beginner with node.js, and I'm not seeming to get this to work.
function sleep(milliSeconds){
var startTime = new Date().getTime();
while (new Date().getTime() < startTime + milliSeconds);
}
var isRequestComplete = false;
while(isRequestComplete == false){
console.log("in make request");
var querystring = require('querystring');
var data = querystring.stringify({
username: 'username',
password: 'password',
action: 'convert',
voice: 'engfemale1',
text: 'stuff and things, this should take longer than one request.'
});
var options = {
host: 'ws.ispeech.org',
port: 80,
path: '/api/rest/1.5',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': data.length
}
};
var http = require('http');
var req = http.request(options, function(res) {
console.log("got response");
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log("body: " + chunk);
if(chunk.indexOf("finished") != -1){
isRequestComplete = true;
}
});
});
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
req.write(data);
req.end();
console.log("completed");
sleep(5000);
}
For whatever reason the http request does not send a response back, ever. Unless the code is fully finished, so in the while loop I never get a response back. Thus the loop never ends. The username and password in my program are inputted, here they are not for confidentiality. Thanks for reading.
this is NOT the way to get your code to sleep! A while loop isn't "sleeping" it's processing as fast as it can. In you case it's grabbing date after date after date trying to get to your destination.
take a look here to see how this *should work.
http://nodejs.org/api/http.html
Have a look at the very first http-server example on http://nodejs.org/.
You have to create an http-server that listens for requests from browsers that arrive at the specified IP-Address:Port. Once a request arrives, the server send the specified response to the browser.

Categories

Resources