25

I have the following code :

var https        = require('https');
var http         = require('http');
var express      = require('express');
var app          = express();
var router       = express.Router();

app.use('/', router);

//have 'server' listen for https
var server = https.createServer(config.sslCredential, app);
server.listen(config.serverPort);

//listen server on http, and always redirect to https
var httpServer = http.createServer(function(req,res){
    res.redirect(config.serverDomain+req.url);
});
httpServer.listen(config.httpServerPort);

but somehow I can't get the https request to be redirected into https request, how should I do this correctly on node.js with express 4.x ?

d-cubed
  • 1,034
  • 5
  • 30
  • 58
uray
  • 11,254
  • 13
  • 54
  • 74

2 Answers2

40

Quoting a middleware solution from my own answer (which btw was on express 3.0)

app.all('*', ensureSecure); // at top of routing calls

http.createServer(app).listen(80)
https.createServer(sslOptions, app).listen(443)

function ensureSecure(req, res, next){
  if(req.secure){
    // OK, continue
    return next();
  };
  // handle port numbers if you need non defaults
  // res.redirect('https://' + req.host + req.url); // express 3.x
  res.redirect('https://' + req.hostname + req.url); // express 4.x
}
Community
  • 1
  • 1
Plato
  • 10,812
  • 2
  • 41
  • 61
  • 11
    Just as an FYI to anyone using Heroku, ```req.secure``` will not work. See the answer here: http://stackoverflow.com/questions/32952085/express-js-redirect-to-https-and-send-index-html – Will Hitchcock Oct 05 '15 at 16:35
  • 4
    `req.host` (express 3.x) is now `req.hostname` (express 4.x) – Claudiu Hojda Mar 29 '16 at 15:21
  • Same goes for Elastic Beanstalk, or any other EC2 instance behind an ELB, where the ELB terminates the HTTPS on behalf of the server. – Elad Nava Jul 12 '16 at 07:29
  • Shouldn't you be doing this rerouting at the level of something like Nginx? – kuanb Dec 14 '16 at 00:54
  • Not necessarily. If your server is sitting behind a service like Cloudflare having another layer of nginx in between you and Cloudflare (which uses nginx) is extra complexity you may not need. Depends on your TLS setup with Cloudflare as well - I'm using HTTPS between Cloudflare and my server, so I need to do this redirect in node but it's not a big overhead. – Bart Read Jan 23 '17 at 20:37
  • 6
    As of 5/2017 w/ Express v 4.8.0: `function ensureSecure(req, res, next){ if(req.headers['x-forwarded-proto'] === 'https'){ // OK, continue return next() }; res.redirect('https://' + req.headers.host) }` – Max Phillips May 10 '17 at 21:01
  • 5
    @PhilAndrews solution of using req.headers['x-forwarded-proto'] is valid only when the express server is behind a load balancer which injects the header x-forwarded-proto – educalleja Nov 14 '17 at 21:41
3

You can do redirection to https like this:

app.enable('trust proxy')
app.use((req, res, next) => {
    req.secure ? next() : res.redirect('https://' + req.headers.host + req.url)
})
Sharhabeel Hamdan
  • 1,273
  • 13
  • 15