I have an express server deployed on Heroku: https://server.mydomain.com
and a Next.js React app also deployed on Heroku: https://app.mydomain.com
Both have their SSL certificates automatically configured by Heroku, and when I visit the https domains, they work as expected.
The problem I have is that when I visit http://app.mydomain.com, it does not redirect to https://app.mydomain.com.
All the solutions I've found online point to forcing SSL on the server:
x-forwarded-proto
value: /* At the top, with other redirect methods before other routes */
app.get('*',function(req,res,next){
if(req.headers['x-forwarded-proto']!='https')
res.redirect('https://app.mydomain.com'+req.url)
else
next() /* Continue to other routes if we're not redirecting */
})
These solutions work fine for the server requests, but loading a React client page does not necessarily trigger app.get()
. Obviously, a React client can run independently of a server.
So the question is: How does someone force https for a subdomain Next.js React client app on Heroku? Without using express server methods?
I do this in one of my production applications.
We prepare the next app object and init an express server. This is done in the server.js file. You can read more about it in the docs about a custom server.
Next.js also has an example in their github in the examples folder about a custom express server. It's here.
const express = require('express');
const next = require('next');
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();
app
.prepare()
.then(() => {
const server = express();
server.use((req, res, next) => {
const hostname = req.hostname === 'www.app.domain.com' ? 'app.domain.com' : req.hostname;
if (req.headers['x-forwarded-proto'] === 'http' || req.hostname === 'www.app.domain.com') {
res.redirect(301, `https://${hostname}${req.url}`);
return;
}
res.setHeader('strict-transport-security', 'max-age=31536000; includeSubDomains; preload');
next();
});
server.get('*', (req, res) => handle(req, res));
server.listen(
4242,
error => {
if (error) throw error;
console.error('Listening on port 4242');
}
);
})
.catch(error => {
console.error(error);
process.exit(1);
});
As for deploying to Heroku you should be able to just customize the npm start script to start nextjs like so:
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start"
}
Heroku also runs npm run build automatically so it should build the app for you.
Heroku does not currently "offer out of the box" functionality to force the use of https
for node apps.
However, with the release of Nextjs v12 you can accomplish this without having to setup a custom server and use middleware instead.
See this answer for example code and advantages of middleware
vs custom server
.
I also published a npm package to handle this:
import sslRedirect from 'next-ssl-redirect-middleware';
export default sslRedirect({});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With