Jake Jake - 2 months ago 15x
Node.js Question

Automatic HTTPS connection/redirect with node.js/express

I've been trying to get HTTPS set up with a node.js project I'm working on. I've essentially followed the node.js documentation for this example:

// curl -k https://localhost:8000/
var https = require('https');
var fs = require('fs');

var options = {
key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'),
cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem')

https.createServer(options, function (req, res) {
res.end("hello world\n");

Now, when I do

curl -k https://localhost:8000/

I get

hello world

as expected. But if I do

curl -k http://localhost:8000/

I get

curl: (52) Empty reply from server

In retrospect this seems obvious that it would work this way, but at the same time, people who eventually visit my project aren't going to type in https://yadayada, and I want all traffic to be https from the moment they hit the site.

How can I get node (and Express as that is the framework I'm using) to hand off all incoming traffic to https, regardless of whether or not it was specified? I haven't been able to find any documentation that has addressed this. Or is it just assumed that in a production environment, node has something that sits in front of it (e.g. nginx) that handles this kind of redirection?

This is my first foray into web development, so please forgive my ignorance if this is something obvious.


Ryan, thanks for pointing me in the right direction. I fleshed out your answer (2nd paragraph) a little bit with some code and it works. In this scenario these code snippets are put in my express app:

// set up plain http server
var http = express.createServer();

// set up a route to redirect http to https

// have it listen on 8080

The https express server listens ATM on 3000. I set up these iptables rules so that node doesn't have to run as root:

iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8080
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 443 -j REDIRECT --to-port 3000

All together, this works exactly as I wanted it to.