Alan Alan - 6 months ago 48
Node.js Question

Enabling HTTPS on express.js

I'm trying to get HTTPS working on express.js for node, and I can't figure it out.

This is my

app.js
code.

var express = require('express');
var fs = require('fs');

var privateKey = fs.readFileSync('sslcert/server.key');
var certificate = fs.readFileSync('sslcert/server.crt');

var credentials = {key: privateKey, cert: certificate};


var app = express.createServer(credentials);

app.get('/', function(req,res) {
res.send('hello');
});

app.listen(8000);


When I run it, it seems to only respond to HTTP requests.

I wrote simple vanilla
node.js
based HTTPS app:

var fs = require("fs"),
http = require("https");

var privateKey = fs.readFileSync('sslcert/server.key').toString();
var certificate = fs.readFileSync('sslcert/server.crt').toString();

var credentials = {key: privateKey, cert: certificate};

var server = http.createServer(credentials,function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
});

server.listen(8000);


And when I run this app, it does respond to HTTPS requests. Note that I don't think the toString() on the fs result matters, as I've used combinations of both and still no es bueno.




EDIT TO ADD:

For production systems, you're probably better off using Nginx or HAProxy to proxy requests to your nodejs app. You can setup nginx to handle the ssl requests and just speak http to your node app.js.

EDIT TO ADD (4/6/2015)

For systems on using AWS, you are better off using EC2 Elastic Load Balancers to handle SSL Termination, and allow regular HTTP traffic to your EC2 web servers. For further security, setup your security group such that only the ELB is allowed to send HTTP traffic to the EC2 instances, which will prevent external unencrypted HTTP traffic from hitting your machines.



Answer

In express.js (since version 3) you should use that syntax:

var fs = require('fs');
var http = require('http');
var https = require('https');
var privateKey  = fs.readFileSync('sslcert/server.key', 'utf8');
var certificate = fs.readFileSync('sslcert/server.crt', 'utf8');

var credentials = {key: privateKey, cert: certificate};
var express = require('express');
var app = express();

// your express configuration here

var httpServer = http.createServer(app);
var httpsServer = https.createServer(credentials, app);

httpServer.listen(8080);
httpsServer.listen(8443);

In that way you provide express middleware to the native http/https server

If you want your app running on ports below 1024, you will need to use sudo command (not recommended) or use a reverse proxy (e.g. nginx, haproxy).