Redirect http to https on heroku (and node generally)

This is 2016 and there is no excuse to still using http.

Because your visitors will often type your domain directly in the address bar of their browser (e.g. mako.ai) without explicitely appending https:// you will have to redirect them to https.

This particular example assumes that your are serving AngularJS or any other kind of SPA framework hosted on heroku, but it should work on more generally with any type of express based set up.

The code

In your web.js use the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var express = require('express');
var http = require('http');

var app = express();

app.use(express.static('' + __dirname,{index:false}));

/* Redirect http to https */
app.get('*',function(req,res,next){
if(req.headers['x-forwarded-proto']!='https'&&process.env.NODE_ENV === 'production')
res.redirect('https://'+req.hostname+req.url)
else
next() /* Continue to other routes if we're not redirecting */
});

app.use('/*', function(req, res){
res.sendFile(__dirname + '/index.html');
});

var server = http.createServer(app);
server.listen(process.env.PORT || 5000);

Explanation

The magic happens in this bit:

1
2
3
4
5
6
7
8

/* Redirect http to https */
app.get('*',function(req,res,next){
if(req.headers['x-forwarded-proto']!='https'&&process.env.NODE_ENV === 'production')
res.redirect('https://'+req.hostname+req.url)
else
next() /* Continue to other routes if we're not redirecting */
});

In the if block, req.headers['x-forwarded-proto'] should be equal to https.

In addition, when testing our code locally we don’t want to trigger the redirect since we don’t have a ssl certificate set up on localhost. Therefore we also use process.env.NODE_ENV === 'production' inside the condition to make sure that this will only run on Heroku, which has the NODE_ENV environment variable set to production.

If both these conditions are met, this means someone is trying to access our app though http. We need to swap http for https and redirect them to the new url. To reconstruct the url that they are trying to call we use req.hostname in combination with req.url.

And finally we redirect using res.redirect().