1

On a Heroku-hosted node app, I want to redirect all HTTP traffic to HTTPS without running a separate app server.

A previous post Automatic HTTPS connection/redirect with node.js/express recommended setting up iptables

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

I'm not very expert - but does anyone know how to do this on Heroku? The goal is route http to https - whatever accomplishes that in the most efficient way.

Thanks!

Community
  • 1
  • 1
metalaureate
  • 7,572
  • 9
  • 54
  • 93

1 Answers1

2

I check https within Express and redirect if necessary:
(are you using Express?)

function requireSecure(req, res, next){
  if(!req.secure){
    var port = app.myConfig.httpsPort || 443;
    if(port != 443){
      res.redirect('https://'+req.host+':'+port+req.originalUrl);
      console.log('redirecting to https://'+req.host+':'+port+req.originalUrl);
    } else {
      res.redirect('https://'+req.host+req.originalUrl);
      console.log('redirecting to https://'+req.host+req.originalUrl);
    };   
  } else {
    next();
  };   
}

// place before any other route to ensure all requests https
app.all('*', requireSecure); 

// You can instead protect individual routes like this:
app.get('/account' 
, requireSecure
, function(req, res, next){
  res.send(200, 'This route is definitely secure!')
});

// I THINK (but haven't tested,) that you can also place this 
// function as middleware in Express's stack, above your router 
// (but possibly below the static files handler, if you don't need https for those)
app.configure(function(){
  app.set('views', __dirname + '/views');
  app.set('view options', {layout:false});
  app.set('view engine', 'jade');
  app.use(requireSecure);
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(app.router);
  app.use(express.static(__dirname + '/public'));
});

// Listen to both http and https protocols:
var http  = require('http');
var https = require('https');
http.createServer(app).listen(80);
https.createServer(options, app).listen(443);
Plato
  • 10,812
  • 2
  • 41
  • 61
  • does this require me to have a separate http server running? I currently only define `//Create server var express = require('express'), app = express() , https = require('https') , server = https.createServer(options,app) , io = require('socket.io').listen(server);` – metalaureate Jul 17 '13 at 21:30
  • 1
    Yes, if you want requests to `http://yourproject.heroku.net/something` to forward to https, you do indeed have to start an http server to listen for those. As you only have an https server, you are guranteed that all requests to your routes are already https (the cost being that http requests fail.) Note that you can start the http server alongside the https server in the same express app. Requests to either protocol will go through the Express routing stack. (see edit) – Plato Jul 17 '13 at 21:33