Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Express.js redirect to HTTPS and send index.html

I have a simple Express.js instance that's serving up static assets for a single page Angular app. I set up some middleware on the Express config so that index.html is returned for all routes and Angular can load from there.

More recently, I set up SSL on Heroku and I want to make sure that all traffic that comes in from HTTP is redirected to HTTPS. I tried to combine the suggested solution from this post with what I have now, but end up in an endless redirect loop.

In short, I need all traffic to be redirected from HTTP to HTTPS and the index.html file to be sent for all requests. What am I doing wrong here?

var gzippo = require('gzippo');
var express = require('express');
var morgan = require('morgan');
var app = express();

// set environment variables
var env = app.get('env') || 'development';

app.use(morgan('dev'));

// serve static assets
app.use(gzippo.staticGzip("" + __dirname + "/dist"));
app.use("/js", express.static(__dirname + "/dist/scripts"));
app.use("/fonts", express.static(__dirname + "/fonts"));
app.use("/img", express.static(__dirname + "/dist/assets/images"));
app.use("/css", express.static(__dirname + "/dist/styles"));


// Redirect all HTTP traffic to HTTPS
function ensureSecure(req, res, next){
  if(req.secure){
    // OK, continue
    return next();
  };
  res.redirect('https://'+req.hostname+req.url); // handle port numbers if you need non defaults
};


// Always send index.html
function sendIndex(req, res, next) {
  res.sendfile('index.html', { root: __dirname + "/dist/"});
}


// Handle environments
if (env == 'production') {
  app.all('*', ensureSecure);
}

app.all('/*', sendIndex);

// Start server
app.listen(process.env.PORT || 5000);
like image 768
Will Hitchcock Avatar asked Oct 05 '15 15:10

Will Hitchcock


People also ask

Can we send HTML file as response in Express?

js and Express applications, res. sendFile() can be used to deliver files. Delivering HTML files using Express can be useful when you need a solution for serving static pages.

How use redirect in Express js?

redirect() function lets you redirect the user to a different URL by sending an HTTP response with status 302. The HTTP client (browser, Axios, etc.) will then "follow" the redirect and send an HTTP request to the new URL as shown below. const app = require('express')(); // The `res.

Does Express js support https?

By simply installing the Express NodeJS package and creating a simple configuration script, you can have a secure web service running over HTTPS.


1 Answers

Heroku terminates SSL connections at the load balancer level, so req.secure will never be true, because your connection to heroku's load balancer is not using SSL, thus creating an infinite redirect loop.

You have to check the X-Forwarded-Proto header instead:

if(req.headers["x-forwarded-proto"] === "https"){
  // OK, continue
  return next();
};
res.redirect('https://'+req.hostname+req.url);

Edit: you can also set app.enable("trust proxy") to have express check the headers automatically. See http://expressjs.com/guide/behind-proxies.html

like image 109
Philippe Avatar answered Sep 20 '22 09:09

Philippe