I have an application up and running on Heroku with Express.js on Node.js with https
. How do I identify the protocol to force a redirect to https
with Node.js on Heroku?
My app is just a simple http
-server, it doesn't (yet) realize Heroku is sending it https
-requests:
// Heroku provides the port they want you on in this environment variable (hint: it's not 80) app.listen(process.env.PORT || 3000);
The Heroku router doesn't have this feature. Show activity on this post. As of July 2019, Heroku supports HTTPS redirects to OTHER DOMAINS OR SUBDOMAINS (a redirect cannot point to itself). All you have to do is configure a URL record for your domain as outlined in this post.
Heroku uses the lockfiles, either the package-lock. json or yarn.
As of today, 10th October 2014, using Heroku Cedar stack, and ExpressJS ~3.4.4, here is a working set of code.
The main thing to remember here is that we ARE deploying to Heroku. SSL termination happens at the load balancer, before encrypted traffic reaches your node app. It is possible to test whether https was used to make the request with req.headers['x-forwarded-proto'] === 'https'.
We don't need to concern ourselves with having local SSL certificates inside the app etc as you might if hosting in other environments. However, you should get a SSL Add-On applied via Heroku Add-ons first if using your own certificate, sub-domains etc.
Then just add the following to do the redirect from anything other than HTTPS to HTTPS. This is very close to the accepted answer above, but:
- Ensures you use "app.use" (for all actions, not just get)
- Explicitly externalises the forceSsl logic into a declared function
- Does not use '*' with "app.use" - this actually failed when I tested it.
- Here, I only want SSL in production. (Change as suits your needs)
Code:
var express = require('express'), env = process.env.NODE_ENV || 'development'; 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(); }; app.configure(function () { if (env === 'production') { app.use(forceSsl); } // other configurations etc for express go here... });
Note for SailsJS (0.10.x) users. You can simply create a policy (enforceSsl.js) inside api/policies:
module.exports = function (req, res, next) { 'use strict'; if ((req.headers['x-forwarded-proto'] !== 'https') && (process.env.NODE_ENV === 'production')) { return res.redirect([ 'https://', req.get('Host'), req.url ].join('')); } else { next(); } };
Then reference from config/policies.js along with any other policies, e.g:
'*': ['authenticated', 'enforceSsl']
The answer is to use the header of 'x-forwarded-proto' that Heroku passes forward as it does it's proxy thingamabob. (side note: They pass several other x- variables too that may be handy, check them out).
My code:
/* 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://mypreferreddomain.com'+req.url) else next() /* Continue to other routes if we're not redirecting */ })
Thanks Brandon, was just waiting for that 6 hour delay thing that wouldn't let me answer my own question.
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