Listen on HTTP and HTTPS for a single express app


Question

Can I create an Express server listening on both HTTP and HTTPS, with the same routes and the same middlewares?

Currently I do this with Express on HTTP, with stunnel tunneling HTTPS to Express, but I prefer a pure Node solution.

I can do it with this code, but using the handle method that is marked as private:

var express = require( 'express' )
    , https = require("https")
    , fs = require( 'fs' );

var app = express.createServer();
// init routes and middlewares
app.listen( 80 );

var privateKey = fs.readFileSync( 'privatekey.pem' ).toString();
var certificate = fs.readFileSync( 'certificate.pem' ).toString();
var options = {key: privateKey, cert: certificate};
https.createServer( options, function(req,res)
{
    app.handle( req, res );
} ).listen( 443 );
1
49
12/2/2011 1:28:13 PM

Accepted Answer

You can share the implementation via something like:

var register = function (app) {
    // config middleware
    app.configure({

    });

    // config routes
    app.get(...);
};

var http = express.createServer();
register(http);
http.listen(80);

var https = express.createServer({ key: /* https properties */ });
register(https);
https.listen(443);
24
12/2/2011 2:16:41 PM

As a possible update to this question, you might want to check out the changes here for express 3. The change document says:

The return value of express() is a JavaScript Function, encapsulating everything that makes an Express app tick. This means you can easily setup HTTP and HTTPS versions of your application by passing it to node's http.createServer() and https.createServer():

In Express 3, express.createServer() is now express()

Here is a complete example for express 3:

var fs = require('fs')
    , https = require('https')
    , http = require('http')
    , express = require('express')
    , keys_dir = 'keys/'
    , server_options = {
        key  : fs.readFileSync(keys_dir + 'privatekey.pem'),
        ca   : fs.readFileSync(keys_dir + 'certauthority.pem'),
        cert : fs.readFileSync(keys_dir + 'certificate.pem')
      }
    , app = express();
app.configure(function(){
  app.use(express.cookieParser());
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(express.session( { secret: '' } ));
  app.use(app.router);
});
app.configure('development',function(){
  app.use(express.static(__dirname + '/public'));
  app.use(express.errorHandler({dumpExceptions: true, showStack:true}));
  app.set('view options', { pretty: true });
});
app.get('/', function(req, res){
  res.send('Hello World!');
});
https.createServer(server_options,app).listen(7000);
http.createServer(app).listen(8000);

Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon