node.js - push data to client - only one client can be connected? - node.js

I am trying to create a server-side solution which periodically pushes data to the client (no client-side polling) via node.js. The connection should be open permanently and whenever the server has new data, it pushes it down to the client.
Here is my simple sample script:
var sys = require('sys'),
http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
sys.puts('Start sending...');
setInterval(function(){
res.write("<script type='text/javascript'>document.write('test<br>')</script>");
}, 10000);
}).listen(8010);
This basically works, but it seems that only one client at a time can be connected.
If I open http://127.0.0.1:8010/ with my browser I see every 10 seconds the new output written. But when I open another tab with the same url, it just loads forever. Only if I close the first tab, I get conent from the server.
What do I need to do in order to server multiple clients?

This is definitely a bug, what happens is that the Browser re-uses the same connection due to keep-alive and HTTP/1.1 and Node screws up.
You can see this at work in Opera11, open the page twice, it's the exact same page, using the exact same connection.
Curl and everything that doesn't set Connection: keep-alive works just fine, but Browsers fail to open the same page twice. Although you can open 'localhost:8010' and 'localhost:8010/foo' and it will work on both pages.
Note: This only affects GET requests, POST requests work just fine since there's no re-using of the connection.
I've filed an issue on this.

You should use socket.io. It handles all the heavy lifting for you and is a really cool library.

Be careful with this!
node.js is non-blocking but at the same time handles only 1 connection at a time. What you did is put the node into a dead state, that's why you see data on the second client when you close the first.

Related

why subsequent HTTP requests

My JavaScript makes that ajax call which retrieves a JSON array.
I am trying simulate long running HTTP REST call request that takes longer to return the results.
The way I do it is delay writing anything to the response object on the server side until 5 minutes elapsed since the request landed. After that I set the status to 200 and write the response with the JSON ending the stream.
Putting a breakpoint on the serve side I realize that the request shows up second time but the browser's Network tab does not show another request being made.
It may not be relevant but I am using browsersync middlewars to serve this JSON and write the bytes and end the response in setTimeout().
setTimeout(()=> {
res.statusCode = 200;
res.write(data);
res.end();
});
Question:
Anyone has any explanation as to why this is happening ? And if there is a way to simulate this in another ways ?
In most cases the browser should retry if connection is closed before response. This is a link to the details => HTTP spec Client Behavior if Server Prematurely Closes Connection
BTW it might help you use the chrome throttling options on the network section of dev tools (F12)

Node.js http GET request takes substantially longer than browser, REST client, et al

I am try to make a simple GET request in Node.js and the request takes 3-5 seconds to resolve whereas the same request in a browser or REST client takes ~400ms. The server to which I am making the request is controlled by our server team, but before I bother them with request/resource monitoring, I was going to ping the community to see if there were any "hey, check this setting first" kind of tips you guys could offer.
The code essentially forwards incoming requests to our server:
http.createServer(function (req, res) {
http.request({
host: "our.private.host",
port: 8080,
path: req.url,
headers: req.headers
}, function () {
res.end("DONE: " + Date.now());
}).end();
}).listen(8001);
I open my browser and type in the following URL:
http://localhost:8001/path/to/some/resource
... which gets forwarded on to the final destination:
http://our.private.host:8080/path/to/some/resource
Everything is working fine and I am getting the response I want, but it takes 3-5 seconds to resolve. If I paste the final destination URL directly in the browser or a REST client, it resolves quickly. I don't know much about our server, unfortunately - but I am looking more for node tips at this point. Note, the request pool isn't maxed out as I am only making 1 request at a time from my local machine.
The first step is gather some info on where the request is taking its time by looking at the exact timing of the network activity on your node server. You can do that by getting a tool that watches all network activity. I personally use Fiddler, but I know that WireShark is popular too.
Once that tools is installed and active, you can then see how long all these various steps in the process of your request are taking:
DNS request to resolve target IP address
Time to connect to the target server
Time to send the http request
Time to receive the http request
Time to send response back to original request
Understanding which of these operations is much longer than expected will give you an idea where to look further for the problem.
FYI, there are pre-built tools such as nginx that can do this type of proxying by just setting some values in a configuration file without any custom coding.

Node.js+express+mongodb handling two http get requests fired almost at the same time

I have a node.js+express+mongo DB app where,
app.get('/test/:testString', function (req, res) {
console.log('req.params.testString: %s ', req.params.testString);
... insert to a collection....
from my client side, I fired two http get almost at the same time. I thought there should be two console.log print out for these two requests. However, strangely, only the second request's log shows and only the second request goes thru the collection insertion. On my server side terminal, I can see two http get requests arrived. Any idea?
Regards
Hammer
More:#CFrei # Peter
I think I know the cause. I have http://www.google.com in my testString. If I remove '//' and '/', then I can see the log printed out. I have already used NSUTF8StringEncoding in my native firing of http get. Any special handling need to be added on express side?
If the client is a browser my first guess would be browser connection management interfering. Try using curl on the command line instead to test.

node.js - after get request, script does not return to console

Here is a simple script
var http = require("http");
http.get( WEBSITE, function(res) {
console.log("Does not return");
return;
});
if WEBSITE variable is 'http://google.com' or 'http://facebook.com' script does not return to console.
but if WEBSITE variable is 'http://yahoo.com' or 'http://wikipedia.org' it returns to console. What is the difference?
By "return to console" I'm assuming you mean that node exits and drops you back at a shell prompt.
In fact, node does eventually exit for all of those domains you listed. (You were just impatient.)
What you are seeing is the result of HTTP keep-alives. By default, node keeps the TCP connection open after a HTTP request completes. This makes subsequent requests to the same server faster. As long as a TCP connection is still open, node will not exit.
Eventually, either node or the server will close the idle connection (and thus node will exit). It's likely that Google and Facebook allow idle connections to live for longer amounts of time than Yahoo and Wikipedia.
If you want your script to make a request and exit as soon as it completes, you need to disable HTTP keep-alives. You can do this by disabling Agent support.
http.get({ host:'google.com', port:80, path:'/', agent:false }, function(res) {
...
});
Only disable the Agent if you need this specific functionality. In a normal, long-running app, disabling the Agent can cause many problems.
There are also some other approaches you can take to avoid keep-alives keeping node running.

Shutting down a Node.js http server in a unit test

Supposed I have some unit tests that test a web server. For reasons I don't want to discuss here (outside scope ;-)), every test needs a newly started server.
As long as I don't send a request to the server, everything is fine. But once I do, a call to the http server's close function does not work as expected, as all made requests result in kept-alive connections, hence the server waits for 120 seconds before actually closing.
Of course this is not acceptable for running the tests.
At the moment, the only solutions I'd see was either
setting the keep-alive timeout to 0, so a call to close will actually close the server,
or to start each server on a different port, although this becomes hard to handle when you have lots of tests.
Any other ideas of how to deal with this situation?
PS: I had a asked How do I shutdown a Node.js http(s) server immediately? a while ago, and found a viable way to work around it, but as it seems this workaround does not run reliably in every case, as I am getting strange results from time to time.
function createOneRequestServer() {
var server = http.createServer(function (req, res) {
res.write('write stuff');
res.end();
server.close();
}).listen(8080);
}
You could also consider using process to fork processes and kill them after you have tested on that process.
var child = fork('serverModuleYouWishToTest.js');
function callback(signalCode) {
child.kill(signalCode);
}
runYourTest(callback);
This method is desirable because it does not require you to write special cases of your servers to service only one request, and keeps your test code and your production code 100% independant.

Resources