Force https/ssl and www on a Node JS application running on Google App Engine/Flex
Found myself searching for hours on how to redirect http traffic to https/ssl and non-www to www on a GAE / flex environment with a Node JS app and in my head i was like: Hey Google! This should be something easy and straightforward like a “gcloud” command.. but it’s not!
Note: I’m using angular universal to serve a landing page and needed http to https/ssl and non-www to www to improve my SEO
Note 2: Want to avoid all this headache? Just use Cloudflare 😛
What I’ve tried before solving my problem:
- 1. redirect directly in my application (winner)
- 2. change app.yaml settings
- 3. change GAE NGINX config
- 4. use google load balancer
I’m gonna describe my trials before showing how I’ve managed to solve the problem for understanding purposes so if you’re in a hurry just jump to the final section.
1. Redirect inside my node/express application
This was my bet since the beginning and it paid off in the end but before getting there it wasn’t working as i expected.
Started by creating a middleware to handle the cases i needed:
- http to https/ssl
- non-www to www
This is how the middleware looked at the beginning:
Almost did the job but the problem here was
!req.secure cause my node/express application(generated by angular universal) doesn't create the server with express https, so
req.secure is always
At this point non-www was redirecting fine to www but then it got inside a redirect loop because it would always have
req.secure === false. So it would always fall inside the secure clause.
Also, a big problem but easy to solve is that google app engine will try liveness_check and readiness_check routes with a different address(usually an IP address) so the app will never complete deploy cause google won’t be able to get a response from these routes, it will fall on one of the first clauses.
At this time I’ve found a possible solution for https/ssl redirect using app.yaml settings, so went to the next step.
2. Redirect http to https/ssl using app.yaml settings
At first i thought this was going to be the right solution but after several trials(and time spending deploys -.-) I found that it only works for standard environment, which is not my case.
Anyways, this is what i’ve tried at this stage, adding this config on my app.yaml:
As said before, it works only on GAE standard environment, which again is not my case.
3. Redirect http to https/ssl changing GAE NGINX config
This is the most found solution on stackoverflow for this problem but it didn’t work for me and for most people there.
Anyways, here are the steps I’ve done:
- Create a file called
nginx-app.configat the root of your project
- make sure this file is deployed at the root folder along with your build
Not sure why it didn’t work but it drove me to the right direction later on:
http_x_forwarded_proto = 'http'
We’ll talk about this soon.. before testing anything else and already tired of 10 minutes for each test/deploy I found a possible solution using google load balancer.
4. Redirect http to https/ssl using Google Load Balancer
It’s possible to solve this issue using this strategy but I didn’t even tried because it seems that google charge for this service and I don’t wanna pay for something simple that should be done out of the box like this.
So.. No steps on this step.
Since the non-www to www was solved I decided to give another change on setting my redirects inside my node/express application for http to https/ssl but had to solve 2 problems from my first trial:
- GAE will use an IP address to know if the application is live, it will fall under the non-www to www clause(imagine:
The nginx solution gave me a direction to look for so what I’ve done was placing 2 extra clauses:
- skip request from IP addresses and localhost(for local testing)
x-forwarded-protoheader to check for ssl
this is the final result that worked:
Worked, pretty awesome!