How do I programmatically shut down an instance of ExpressJS?

Unit TestingTestingnode.jsExpressmocha.js

Unit Testing Problem Overview


I'm trying to figure out how to shut down an instance of Express. Basically, I want the inverse of the .listen(port) call - how do I get an Express server to STOP listening, release the port, and shutdown cleanly?

I know this seems like it might be a strange query, so here's the context; maybe there's another way to approach this and I'm thinking about it the wrong way. I'm trying to setup a testing framework for my socket.io/nodejs app. It's a single-page app, so in my testing scripts (I'm using http://visionmedia.github.com/mocha/">Mocha</a>;, but that doesn't really matter) I want to be able to start up the server, run tests against it, and then shut the server down. I can get around this by assuming that either the server is turned on before the test starts or by having one of the tests start the server and having every subsequent test assume it's up, but that's really messy. I would much prefer to have each test file start a server instance with the appropriate settings and then shut that instance down when the tests are over. That means there's no weird dependencies to running the test and everything is clean. It also means I can do startup/shutdown testing.

So, any advice about how to do this? I've thought about manually triggering exceptions to bring it down, but that seems messy. I've dug through Express docs and source, but can't seem to find any method that will shut down the server. There might also be something in socket.io for this, but since the socket server is just attached to the Express server, I think this needs to happen at the express layer.

Unit Testing Solutions


Solution 1 - Unit Testing

Things have changed because the express server no longer inherits from the node http server. Fortunately, app.listen returns the server instance.

var server = app.listen(3000);

// listen for an event
var handler = function() {
  server.close();
};

Solution 2 - Unit Testing

Use app.close(). Full example:

var app = require('express').createServer();
app.get('/', function(req, res){
  res.send('hello world');
});
app.get('/quit', function(req,res) {
  res.send('closing..');
  app.close();
});
app.listen(3000);

Call app.close() inside the callback when tests have ended. But remember that the process is still running(though it is not listening anymore).

If after this, you need to end the process, then call process.exit(0).

Links:

app.close: http://nodejs.org/docs/latest/api/http.html#server.close (same applies for)

process.exit: http://nodejs.org/docs/latest/api/process.html#process.exit

Solution 3 - Unit Testing

//... some stuff 

var server = app.listen(3000);
server.close();

Solution 4 - Unit Testing

I have answered a variation of "how to terminate a HTTP server" many times on different [tag:node.js] support channels. Unfortunately, I couldn't recommend any of the existing libraries because they are lacking in one or another way. I have since put together a package that (I believe) is handling all the cases expected of graceful HTTP server termination.

https://github.com/gajus/http-terminator

The main benefit of http-terminator is that:

  • it does not monkey-patch Node.js API
  • it immediately destroys all sockets without an attached HTTP request
  • it allows graceful timeout to sockets with ongoing HTTP requests
  • it properly handles HTTPS connections
  • it informs connections using keep-alive that server is shutting down by setting a connection: close header
  • it does not terminate the Node.js process

Usage with Express.js:

import express from 'express';
import {
  createHttpTerminator,
} from 'http-terminator';

const app = express();

const server = app.listen();

const httpTerminator = createHttpTerminator({
  server,
});

await httpTerminator.terminate();

Solution 5 - Unit Testing

More recent version of express support this solution:

const server = app.listen(port);

const shutdown = () => {
  server.close();
}

Solution 6 - Unit Testing

You can easily do this by writing a bash script to start the server, run the tests, and stop the server. This has the advantage of allowing you to alias to that script to run all your tests quickly and easily.

I use such scripts for my entire continuous deployment process. You should look at Jon Rohan's Dead Simple Git Workflow for some insight on this.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiondrewwwView Question on Stackoverflow
Solution 1 - Unit TestingRich ApodacaView Answer on Stackoverflow
Solution 2 - Unit TestingSrijan ChoudharyView Answer on Stackoverflow
Solution 3 - Unit Testingаlex dykyіView Answer on Stackoverflow
Solution 4 - Unit TestingGajusView Answer on Stackoverflow
Solution 5 - Unit TestingFilip GórnyView Answer on Stackoverflow
Solution 6 - Unit TestingJosh SmithView Answer on Stackoverflow