ExpressJS multi domain https hosting

1.8k Views Asked by At

I've got a project, where I need to host two websites with two Domains, which point to the same server (1 static IP) with an EpressJS server. During my research I found that, express can be expanded with vhosts. But I could not figure out, how to use them with https. My desire is to have too different express objects so I can access 'foo.com'-requests over appFoo.get() and 'bar.com'-requests via appBar.get() or their POST or JSON-aquivalent. I don't want to use a proxy in either apache, nginx oder node itself. And I'd like to run them both on port 80/443.

1

There are 1 best solutions below

0
On BEST ANSWER
// Includes
var https = require('https');
var express = require('express');
var tls = require('tls');
var vhost = require('vhost');
var fs = require('fs');


// Express objects
var appFoo = express();
var appBar = express();

// SSL Constants
const siteFoo = {
    app: appFoo,
    context: tls.createSecureContext({
        key: fs.readFileSync(__dirname + '/tls/foo.com/privkey.pem').toString(),
        cert: fs.readFileSync(__dirname + '/tls/foo.com/fullchain.pem').toString(),
        ca: fs.readFileSync(__dirname + '/tls/foo.com/chain.pem').toString()
    }).context
};

const siteBar = {
    app: appBar,
    context: tls.createSecureContext({
        key: fs.readFileSync(__dirname + '/tls/bar.com/privkey.pem').toString(),
        cert: fs.readFileSync(__dirname + '/tls/bar.com/fullchain.pem').toString(),
        ca: fs.readFileSync(__dirname + '/tls/bar.com/chain.pem').toString()
    }).context
};

// Sites
var sites = {
    'www.foo.com': siteFoo,
    'foo.com': siteFoo,

    'www.bar.com': siteBar,
    'bar.com': siteBar
}

// Setup vhosts
var exp = express();
for (var s in sites) {
    console.log("add app for " + s);
    exp.use(vhost(s, sites[s].app));
}

// Redirect from http port  to https
var http = require('http');
http.createServer(function (req, res) {
    res.writeHead(301, { "Location": "https://" + req.headers['host'] + req.url });
    console.log(req.headers['host']);
    console.log(req.url);
    res.end();
}).listen(80);

// HTTPS Server
var secureOpts = {
    SNICallback: function (domain, cb) {
        if (typeof sites[domain] === "undefined") {
            cb(new Error("domain not found"), null);
            console.log("Error: domain not found: " + domain);

        } else {
            cb(null, sites[domain].context);
        }
    },
    key: fs.readFileSync(__dirname + '/tls/qarm.de/foo.com/privkey.pem').toString(),
    cert: fs.readFileSync(__dirname + '/tls/qarm.de/foo.com/fullchain.pem').toString(),
    ca: fs.readFileSync(__dirname + '/tls/qarm.de/foo.com/chain.pem').toString()
};

var https = require('https');
var httpsServer = https.createServer(secureOpts, exp);
httpsServer.listen(443, function () {
    console.log("Listening https on port: " + + this.address().port);
});

appFoo.get('/', function(req,res) {
   res.send('Foo.com');
}

appBar.get('/', function(req,res) {
   res.send('bar.com');
}

This code creates two seperate vhost from new express objects, initializes TLS, directes requests to the right object and redirects all traffic from HTTP (Port 80) to HTTPS (443)