I am attempting to setup a server with ExpressJS which uses HTTPS and servers a React app. I want any HTTP requests to be redirected to using HTTPS.
Additional constraint: I am using React router, so the server needs to be able to handle that. e.g. if I request localhost:3000/profile
, I want React Router to handle that, I just need Express to server up index.html
as I had gone to localhost:3000
.
Problem: I think I've been able to setup HTTPS (Chrome complains but I don't mind for now), but I cannot get redirection to work.
For comparison, this is my code for how I setup my HTTP-only server for development (before I ever tried to setup HTTPS):
const express = require('express');
const http = require('http');
const path = require('path');
const app = express();
const DIST_DIR = path.resolve('./dist');
app.use(express.static(DIST_DIR));
app.get('*', (req, res) => {
res.sendFile(path.resolve(DIST_DIR, './index.html'));
});
const devServer = http.createServer(app);
devServer.listen(3000);
Next, I started with this guide. I created a self-signed SSL certificate then set up my application. I then looked at some examples of how to redirect, such as this question.
However, it doesn't seem to be working.
Here is my code at present:
app.use(express.static(DIST_DIR));
app.use((req, res, next) => {
if (req.secure) {
next();
} else {
res.redirect(`https://${req.headers.host}${req.url}`);
}
});
app.get('*', (req, res) => {
res.sendFile(path.resolve(DIST_DIR, './index.html'));
});
const httpServer = http.createServer(app);
httpServer.listen(3080);
const privateKey = // uses FS to get my key
const certificate = // uses FS to get my cert
const credentials = { key: privateKey, cert: certificate };
const httpsServer = https.createServer(credentials, app);
httpsServer.listen(3443);
I can access https://localhost:3443
and navigate the app as expected, and Express properly handles refreshes on pages like /profile
. Great. Chrome complains that "CA root certificate is not trusted. Install this cert in the trusted root certification authorities store" but I haven't put in the work to solve that, because in a real production environment I'd be provided the certificate and key from a trusted source.
However, when I go to http://localhost:3080
, I just end up at http://localhost:3080
. Chrome devtools shows I'm not using HTTPS. Furthermore, I can't go directly to /profile
, as Chrome gives me the error "This site can’t provide a secure connection".
I've tried other methods listed in that stackoverflow question I linked, but they either have the same behavior or straight up don't work. I'm a bit out of my element here and I'm trying to learn, but I don't understand why this isn't working. Any help would be appreciated. Thanks.