Gaj
Gaj

Reputation: 303

Forcing HTTPS for Node.js app on Heroku

I'm having some problems forcing SSL on my node.js app that is deployed to Heroku. I want to force HTTPS in all scenarios. I am also using Express.

I have followed the code on this post: Heroku NodeJS http to https ssl forced redirect (the answer from arcseldon).

I'm testing in Chrome.

Here is my test scenario: If I go to www.mywebsite.com, it re-directs to the https://www.mywebsite.com -> This is working as I expect.

Now I am in https://www.mywebsite.com. If I go into the URL in Chrome and edit the 'https' to just 'http' and it hit enter. It is making the connection just via http (I checked in Chrome developer tools).

Here is my snippets of my code in case I am doing something wrong.

var forceSsl = function (req, res, next) {
    if ( req.headers['x-forwarded-proto'] != 'https'){
      console.log( 'forceSSL req.get = ' + req.get('Host') + ' req.url = ' + req.url );
      return res.redirect('https://' + req.get('Host') + req.url );
    } else {
      console.log( 'No need to re-direct to HTTPS' );
      next();
    }
};

if ('development' == app.get('env')) {
  console.log('Started in dev mode');
  // Other code here

} else if ('production' == app.get('env')) {
  console.log('Started in PROD mode');
  app.use(forceSsl);
  app.use('/public', express.static(__dirname + '/public'));
  app.use(express.errorHandler());
  mongoose.connect(process.env.MONGOHQ_URL);
}

On a side note, I never see the console messages in the 'forceSsl' function.

I have configured my domain to point to the SSL version of the heroku app so I don't know how it is making a connection via HTTP.

Thank you very much in advance for your help.

Edit: In the above test case where I think it is working in Chrome, I think Chrome is intervening and re-directing so it is probably not working as expected.

When I test via curl, I can see that the site accepts a request via HTTP and does not do a re-direct.

Upvotes: 2

Views: 2182

Answers (2)

Joan-Diego Rodriguez
Joan-Diego Rodriguez

Reputation: 2547

Here is a complete example using html5 urls:

var express = require('express');
var http = require('http');

var app = express();

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

app.use('/*', function(req, res){
  if(req.headers['x-forwarded-proto']!=='https'){
    res.redirect(301, 'https://apps.iazi.ch'+req.url);
  }
  res.sendFile(__dirname + '/index.html');
});

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

Upvotes: 1

Gaj
Gaj

Reputation: 303

I think I worked out my problem. I am using a Google Angular app which is served out of the public directory as static files. The declaration for my public directory in the Express 'app.use' was above my 'app.use(forceSsl);'.

Therefore, my static files (e.g. my Angular App) from my public directory were being served out before they even got to my re-routing code. With Express, the ordering of how you use the 'app.use' statements is important.

I re-ordered the 'app.use' for my public directory to be below the 'app.use(forceSsl);' and it seems to work.

Hopefully this will help someone else who has a similar problem.

Upvotes: 3

Related Questions