简体   繁体   中英

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);

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM