node http server stop doesn't shut down connections - node.js

I've been looking for a while in a lot of threads about how to shut down an http server in nodejs.
I couldn't find a simple way to test my web app.
I'm trying to test my server, writing integration test.
I want to simulate errors as well, hence I start the server with different configurations.
For example:
const app = express()
...
app.use('/route', createRouter(argA, argB)
const server = http.createServer(app)
I want to test that if argA throws an error, my server return 500,
as well as argB.
So I want to start the server with a mock of argA that throws,
then close the server and start it again with a mock of argB that throws.
But, the http server of nodejs doesn't close connected sockets,
so I cant do something like this:
beforeEach((done) => server.start(done))
afterEach((done) => server.stop(done))
Where start execute listen and stop execute close.
The server fails to start since the port is already in use.
How can I manage to start and stop the server with different configurations?

Related

Why is my Node.js service stopping unexpectedly under GraalVM?

I have a fairly simple Node.js service that basically just fields a few HTTP requests. This runs fine via the GraalVM node command. However, when I use node --jvm --polyglot service.js My Node service dies shortly after starting. Nothing else in the code has changed.
What is interesting is that the following code seems to kill my Node.js service
const { MongoClient } = require("mongodb")
console.log("got MongoClient")
And when I run Graal Node without --jvm --polyglot everything works fine.
If I comment out the Mongo stuff, running with --jvm --polyglot, everything works fine.
What could possibly be going on where trying to run the MongoDB Node.js driver under GraalVM could be causing problems?
It may not be that it dies, but after starting my HTTP service
const server = app.listen(port, () => console.log(`Server running... test at http://${hostname}:${port}/ping`))
it no longer accepts HTTP requests. ???
The best approach would be to raise an issue on GraalVM's repos, probably on the Graal.js one: https://github.com/oracle/graaljs. It could be a bug.
You can also debug the process and maybe that will reveal additional details of what's happening: https://www.graalvm.org/tools/chrome-debugger/

NodeJS Express - Two NodeJS instances on same port (vhost)

I'm trying to run 2 instances of NodeJS on the same port and server from diffrent server.js files (diffrent dir, config etc). My server provider gave me an information that vhost is running for a diffrent domain, and there is the question. How to handle it in NodeJS Express app ? I've tried to use vhost from https://github.com/expressjs/vhost like that :
const app = express();
const vhost = require('vhost');
app.use(vhost('example1.org', app));
// Start up the Node server
app.listen(4100, () => {
console.log(`Node server listening on 4100`);
});
And for second application like that:
const app = express();
const vhost = require('vhost');
app.use(vhost('example2.org', app));
// Start up the Node server
app.listen(4100, () => {
console.log(`Node server listening on 4100`);
});
But when I'm trying to run second instance I'm getting EADDRINUSE ::: 4100, so vhost doesn't work here.
Do you know how to fix it ?
You can only have one process listen to one port, not just in Node.js, but generally (with exceptions that don't apply here).
You can achieve what you need to one of two ways:
Combine the node apps
You could make the apps into one application, listen once and then forward requests for each host to separate bits of code - if you wanted to achieve code separation still, the separate bits of code could be NPM modules that are actually written and maintained in isolation.
Use webserver to proxy the requests
You could run the 2 node processes on some free port, say 5000 and 5001, and use a webserver to forward requests to it automatically based on host. I'd recommend Nginx for this, as its proxying capabilities are both relatively easy to set up, and powerful. It's also fairly good at not using too many system resources. Apache and others can also be used for this, but my personal preference would be Nginx.
Conclusion
My recommendation would be that you install a webserver and forward requests on the exposed port to the separately running node processes. I'd actually recommend that you run node behind a proxy as default for a project, and only expose it directly in excpetional circumstances. You get a lot of configuration options, security, and scalability benefits if your app already involves a well hardened server setup.

Trying to run node app on fedora server

Ok I am making website and want to use mongo, express, etc. I setup a server using fedora server ISO. The problem is getting node working. I have followed several tutorials, and its all the same. Nothing works. So I have to be doing something wrong. Trying to get the simplest thing to display on screen.
I think the server is running httpd server, whatever fedora has built in. I get the default fedora server page when going to the url. So the server is running and working, just hasn't been configured. When running node on the server do I have to use httpd-node? Or can it be http, etc.
Here is my app.js
const express = require('express')
const app = express()
app.get('/', function (req, res) {
res.send('Hello World!')
})
app.listen(3000, function () {
console.log('Example app listening on port 3000!')
})
And then I have a basic index.html that should be rendered just saying test.
I ssh into the server and run node start, it runs and the console logs the message like it should. But if I go to the address 192.168.1.5, or the domain that points to the server, I get nothing, just a blank page.
If someone can help me get this working, I can actually get to work coding out the application. Any help would be appreciated.
I think you make a confusion. When you build an Express application, you do not need another server at all.
When you start your app with:
app.listen(3000, function () {})
Express returns an http.Server object listening to port 3000.
When you navigate to your local adress on port 3000, you will see your "hello world" message.
It is possible that httpd service is already running in your Fedora environnement on default port 80 (the default port for http, the one your reach when you go to your local adress) but this is an Apache server and you do not need it to run your Nodejs app.
To build a Nodejs server, you can also use httpd-node package, but this is redundant as you're using Express framework.
If you need to serve a simple html file, a method I like for its simplicity is to use ejs template engine, something like this.
res.send('Hello World!') - this is your problem! Why?
How you receive this answer on client side?
Solution: use res.render(..) - for rendering from server or use AJAX on client side for receive this text!
P.S: render page and you don't see blank page anymore! Or use client-server conversation logic with your server through AJAX.
Try 192.168.1.5:3000
If I wrong: show your full project setup...
Test your app with curl (https://curl.haxx.se)! Check connection establishment, and show results here!

node-amqp — proper way to handle connection in Express app?

I'm using Express with node-amqp. My goal is to create amqpConnection and save it to global object before server starts and in Express routes use previously created globals.amqp_connection.
### server.coffee
app.use( ... )
...
# create RabbitMQ connection before server starts
connection = require("amqp").createConnection
host: "localhost"
connection.on "ready", ->
console.log "Got connection.on(\"ready\") event from node-amqp..."
# make amqp_connection accessible from any point of application
globals.amqp_connection = connection
server = globals.http.createServer(app).listen(8082)
console.log "Express server is listening 8082..."
The problem is connection.on "ready"-event is fired eveytime I call a route. I may suppose that's because of Express way of serving http-requests — executing server.js for every route called. So, for every request, a new instance of connection is created and on it's "ready" app tries to create one more instance of Express server.
How to make amqp_connection accessible from any point of my app, but no doubling require("amqp").createConnection() in every point where I need to push something to RabbitMQ?
UPD: or maybe there is no problem with Express. node-amqp seems to fire ready event every second after creation. Don't know if it's correct behavior
Thank you.
Ready event fired multiple 'cause of connection error:
https://github.com/postwait/node-amqp/issues/255

some questions from a node.js newbie

i have just started learning node and i am using node-v0.4.11 on Fedora 12. It installed without any errors and i am able to run some basic programs but there are some things i cant figure out
If i create a server at a port and then if i stop node using Ctrl+C
i cannot use that port again for starting a server without restarting
the system.
my code looks like this
var port=8080;
var count=0;
var http=require('http');
var server = http.createServer(function(req, res) {
count++;
console.log('request no '+count+' received');
res.writeHead(200);
res.end('you are at port '+port);
});
server.listen(port);
console.log('server started at port '+port);
Now when i save the file and execute it the server starts. But when i stop the server from the shell , i cannot start the server again at the port i started before(in this case port 8080).This is bad because every time i have to make changes in that file i have to change the port number too.Can i stop this behavior?
EDIT:
This is the error that i get when i try to start the server at the same port again
Server started at 8080
node.js:203
throw e; // process.nextTick error, or 'error' event on first tick
^
Error: listen EADDRINUSE
at errnoException (net_uv.js:557:11)
at Array.<anonymous> (net_uv.js:632:28)
at EventEmitter._tickCallback (node.js:195:26)
i saw the process list after i terminated node using Ctrl+C and i found node was still running. So i killed it and checked the process list again to make sure it was dead and it was(i could not see it in the process list). Now i again tried to start the server at the same port but i got the same error as above.And once i stop the server and make request from the browser the request hangs up for ever(it keeps on waiting).
My next problem is that in the above when the server starts and i make
the first request count is incremented 3 times and i can see 3
messages at the console. This is just for the first request,if i make
more requests count is just incremented once. Whats wrong?
this problem is solved
My next problem is that if i change res.writeHead(200); to
res.writeHead(404); or any other valid status code like 300 node
gives error at the command line but these are valid status codes and
the server should start and respond to each request according the
status code like Not found for 404. What am i doing wrong?
this problem is solved
I am not able to use Firebug's 'Net' tab to monitor requests when i
send requests to the server created by Node. Is there a way to do so?
Thanks for bearing.
i cannot start the server again at the port i started before
You should not be seeing this behavior, and I cannot reproduce it. Do you get an error message when you try to start the server again? What is it? Once you've stopped the server, do you see any node processes in your process list? If so, can you start your server after you kill them?
count is incremented 3 times and i can see 3 messages at the console
Your browser is sending multiple requests. For example, in Chrome, you might get (1) a pre-fetch request (where Chrome downloads the page it thinks you want), (2) the actual page request, and (3) a request for favicon.ico; your Node app is listening for all requests, not just requests to the / URL. After the initial request, the browser caches the favicon, etc. and doesn't need to request them again.
Try adding console.log(req.url); to your callback and see what URLs the browser is asking for.
any other valid status code like 300 node gives error at the command line
I can't reproduce this problem. What error are you receiving?
I am not able to use Firebug's 'Net' tab to monitor requests when i send requests to the server created by Node
I'm also not able to reproduce this. Firebug and other client-side debugging tools don't know or care what technology is running on the server; it just speaks HTTP.

Resources