Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why cannot I redirect my React app on Heroku from http to https?

I have an app on Heroku that was created using create-react-app. Just today, I got an SSL cert using Heroku's automated(-ish) SSL cert process ExpeditedSSL, and the documentation then suggests rerouting all http requests to https.

I have a server.js file and express I use just to attempt to run middleware and then serve my React app.

I know the SSL cert is working as if I go to https://myapp.com I see my Heroku app, but when I go to http://myapp.com it is not redirected to the https version of my Heroku app.

I have tried many, many solutions today from StackOverflow, Google, and otherwise and none of the the solutions have worked for me. I don't get any errors, either. It just doesn't work.

Attempt using https library:

const https = require("https");
const express = require('express');
const app = express();

app.use(express.static(path.join(__dirname, 'build')));

app.get('/', function (req, res) {
  res.sendFile(path.join(__dirname, 'build', 'index.html'));
});

https.createServer(app).listen(3000);

Another attempt using heroku-ssl-redirect:

var sslRedirect = require('heroku-ssl-redirect');
var express = require('express');
var app = express();

// enable ssl redirect
app.use(sslRedirect(['production'], 301));

app.use(express.static(path.join(__dirname, 'build')));

app.get('*', (req, res, next) => {
  if (req.headers['x-forwarded-proto'] != 'https'){
    res.redirect('https://' + req.hostname + req.url);
  } else {
    next();
  }
});

app.get('/', function (req, res) {
  res.sendFile(path.join(__dirname, 'build', 'index.html'));
});

app.listen(process.env.PORT || 3000);

Attempt using x-forward-proto:

const express = require('express');
const env = process.env.NODE_ENV || 'development';
const bodyParser = require('body-parser');
const path = require('path');
const app = express();

var forceSsl = function (req, res, next) {
  if (req.headers['x-forwarded-proto'] !== 'https') {
    return res.redirect(['https://', req.get('Host'), req.url].join(''));
  }
  return next();
};

if (env === 'production') {
  app.use(forceSsl);
}

app.use(express.static(path.join(__dirname, 'build')));

app.get('/', function (req, res) {
  res.sendFile(path.join(__dirname, 'build', 'index.html'));
});

app.listen(process.env.PORT || 8080);

I've also attempted a number of random node installs from various blogs and SO posts, and nothing has worked. Without any errors I am having a hard time figuring out why this doesn't work.

like image 970
smkarber Avatar asked Feb 20 '18 06:02

smkarber


People also ask

How can I change http to HTTPS in Heroku?

react-boilerplate can enforce https(redirect http to https) on heroku deployed apps(that has extra layer like cloudflare). var sslRedirect = require('heroku-ssl-redirect');const app = express();app. use(sslRedirect()); Now you get all connection to be on https.

Does Heroku use http or HTTPS?

HTTP versions supported Four main versions of HTTP are used in the wild: HTTP/0.9, HTTP/1.0, HTTP/1.1 and HTTP/2. The Heroku router only supports HTTP/1.0 and HTTP/1.1 clients.


1 Answers

UPDATED and SECURE solution below:

Since you are deploying your react app via Heroku using create-react-app and it's buidlpack (recommended, if you are not: create-react-app-buildpack). So as the official docs says:

The web server may be configured via the static buildpack.

The config file static.json should be committed at the root of the repo. It will not be recognized, if this file in a sub-directory

The default static.json, if it does not exist in the repo, is:

{
  "root": "build/",
  "routes": {
    "/**": "index.html"
  }
}

HTTPS-only

Enforce secure connections by automatically redirecting insecure requests to https://, in static.json:

{
  "root": "build/",
  "routes": {
    "/**": "index.html"
  },
  "https_only": true
}

The method by @misterfoxy works but is not the right way!

like image 116
Frederiko Cesar Avatar answered Sep 26 '22 00:09

Frederiko Cesar