Open mike-north opened 7 years ago
Isn't forcing HTTPS in the app server something that is more a leftover from Rails' early days when everyone used HTTPS only for some (sensitive) endpoints while nowadays everyone is (should be) using HTTPS only all of the time in which case nginx would just redirect all HTTP requests to HTTPS so that no requests that are not HTTPS would ever reach the app server?
I'm not saying this is not a problem people have, I'm only saying the answer to them should not be "here is how you enforce HTTPS in Express" but "here's how you fix your nginx config".
100% agree with what @marcoow said, however it's not straight forward to get into nginx config (or even apache rewrite rules) when hosting on a Paas like heroku or elastic beanstalk. Related: https://github.com/heroku/heroku-buildpack-emberjs/issues/8
Any updates on this? I'm currently using heroku-buildpack-emberjs
and need to find a solution to force HTTPS.
@jakeleboeuf I'm in the same situation. Have you found a solution? The only thing I can think of is downloading the buildback, manually using @mike-north 's solution, and then reuploading the custom buildpack to an s3 bucket to use with heroku. Very not ideal but I'm not sure there's another alternative yet?
@jakeleboeuf @konnorbeard Found any other solutions?
There's a solution for Heroku as discussed in this thread: https://github.com/heroku/heroku-buildpack-emberjs/issues/8
what if I do it on nginx? I have nginx with next config:
server {
listen 80 default_server;
server_name mysite.me;
root /usr/share/nginx/html;
gzip on;
gzip_comp_level 5;
gzip_disable "msie6";
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript;
location /health_check {
access_log off;
return 200;
}
location / {
if ($http_x_forwarded_proto != 'https') {
return 301 https://$server_name$request_uri;
}
resolver 8.8.8.8;
proxy_pass https://324234234234.eu-central-1.elb.amazonaws.com:3443;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
server {
listen 80;
server_name www.mysite.me;
return 301 https://mysite.me$request_uri;
}
server {
listen 80;
server_name blog.mysite.me;
return 301 https://mysite.me/blog$request_uri;
}
So Ngnix does redirect from http to https and proxy request to FastBootAppServer.
But when FastBoot tries to redirect It adds port 3443 to host like it ignores request's header Host $host
.
How transitionTo
works on FastBoot? How does FastBoot get host for redirecting?
Please advise how to figure out the problem.
To slightly expand upon what @mike-north wrote, we can have a slightly modified version that prefers HTTPS and naked domains.
For anyone like me having many headaches using Apache ProxyPass, if you decide to forgo Apache altogether.
const enforceHTTPS = (req, res, next) => {
// Header indicates edge server received request over HTTPS
if (req.headers['x-forwarded-proto'] === 'https') {
return next();
} else {
return res.redirect(301, `https://${req.hostname}${req.url}`);
}
};
const enforceNaked = (req, res, next) => {
if(/^www\./.test(req.headers.host)) {
res.redirect(req.protocol + '://' + req.headers.host.replace(/^www\./,'') + req.url,301);
} else {
next();
}
}
let server = new FastBootAppServer({
notifier: notifier,
downloader: downloader,
gzip: true,
beforeMiddleware(app) {
app.use((req, res, next) => {
if (req.headers['user-agent'].indexOf('HealthChecker') >= 0) {
return next(); // Proceed as planned (http or https -- whatever was asked for)
} else {
return enforceHTTPS(req, res, next); // Middleware to force all other HTTP --> HTTPS
}
});
app.use((req, res, next) => {
return enforceNaked(req, res, next);
});
}
});```
Volunteering some example code, as a potential candidate for README. This uses the relatively new
beforeMiddleware
hook to force http traffic to https, with a provision for the EBS health check feature (which seems to come over HTTP unless HTTP is totally disabled for the env).