Redirect all URLs to secured URLs without www in Node.js - node.js

I am using the code below to redirect all my traffic to https version without www i.e. for one my application hosted on a subdomain. It should work for the following cases:
http://subdomain.domain.com
http://www.subdomain.domain.com
https://www.subdomain.domain.com
www.subdomain.domain.com
All the above should redirect to https://subdomain.domain.com.
I am trying out this on my Node.js application.
app.use('*', function(req, res, next) {
// https
if (req.headers["x-forwarded-proto"] == "https") {
// https with www
if (req.headers.host.match(/^www/) !== null) {
res.redirect(301, 'https://' + req.headers.host.replace(/^www\./, '') + req.url);
}
// https without www
else {
next();
}
}
// http
else {
// http with www
if (req.headers.host.match(/^www/) !== null) {
res.redirect(301, 'https://' + req.headers.host.replace(/^www\./, '') + req.url);
}
// http without www
else {
res.redirect("https://subdomain.domain.com" + req.url);
}
}
});
I am not able to get the redirection working. For the fourth URL i.e. www.subdomain.domain.com, I have updated my DNS as well.

Below Code Snippet Check if URL is not secure it redirects to https with replacing www from url.
app.use('*',function(req, res, next){
if (!req.secure) {
res.redirect('https://' + req.headers.host.replace(/\/\/www\./, '') + req.url);
}
next();
})

Related

How can I redirect from non-www to www using heroku and namecheap?

I am using heroku and namecheap on https. How can I redirect non-www to www.
Here's what I tried
app.get("*", function (req, res, next) {
if (
process.env.NODE_ENV === "production" &&
req.headers.host.slice(0, 3) != "www"
) {
res.redirect("https://www." + req.headers.host + req.url, 301);
} else {
next();
}
});
I want to add a setting at the namecheap level. How can I do that?

Why does HTTP -> HTTPS redirect fail in nodejs when no subdomain is specified?

I'm running a nodejs webapp on Heroku and I want to redirect all users that access via http to https with the corresponding URL.
I have it mostly working however the user is redirected to the home page if no subdomain is specified. Any idea what is going on here?
The node rerouting middleware:
app.enable('trust proxy');
app.use((req, res, next) => {
if (req.get('X-Forwarded-Proto') !== 'https') {
res.redirect(`https://${req.headers.host + req.url}`);
} else {
next();
}
});
Works:
http://www.example.com/page redirects to https://www.example.com/page
Fails:
http://example.com/page redirects to https://www.example.com
Because req.url is an inherited property from Node.JS's http module and does not necessarily contain the original URL. Express.JS documentation also states it, https://expressjs.com/en/api.html#req.originalUrl
If you want to retain the original url you should use the correct property, which is originalUrl.
app.enable('trust proxy');
app.use((req, res, next) => {
if (req.get('X-Forwarded-Proto') !== 'https') {
res.redirect(`https://${req.headers.host + req.originalUrl}`);
} else {
next();
}
});

Redirecting HTTP requests to HTTPS not always working

I have an application written using Node. Any requests coming over HTTP is redirected to HTTPS. In some cases the redirection happens successfully (browser receives a HTTP 302) however most of the cases the redirection does not occur(browser receives just a HTTP 200).
What should i do to ensure the redirection always occurs ?
Logic i currently use
module.exports = function(req, res, next) {
console.log("Entering secure redirect route");
if(!req.headers['x-forwarded-proto']) {
console.log("Attempting to access using http protocol");
} else {
console.log("Attempting to access using https protocol");
}
console.log("Attempting to access host " + req.host);
console.log("Attempting to access url " + req.originalUrl);
if(!req.headers['x-forwarded-proto']) {
console.log("Redirecting to " + "https://" + req.host + req.url);
res.redirect("https://" + req.host + req.url);
res.end();
} else {
next();
}
} else {
next();
}
};
It's not enough that the x-forwarded-proto header is set if the value is not HTTPS. Whoever is forwarding the traffic must be accepting HTTP connections.
console.log out the value of x-forwarded-proto every time, and I suspect sometimes the value is HTTP

node js Hapi js and heroku how to handle https

I want to allow only https traffic to my Hapi Js server.
In this thread:
Node.JS, Express and Heroku - how to handle HTTP and HTTPS?
it was accomplished by:
if (process.env.NODE_ENV == 'production') {
app.use(function (req, res, next) {
res.setHeader('Strict-Transport-Security', 'max-age=8640000; includeSubDomains');
if (req.headers['x-forwarded-proto'] && req.headers['x-forwarded-proto'] === "http") {
return res.redirect(301, 'https://' + req.host + req.url);
} else {
return next();
}
});
}
This is a good npm module for this: https://www.npmjs.org/package/hapi-require-https
This is my (fairly hacky) solution:
// redirect all http request to secure route
if ('production' === process.env.NODE_ENV) {
server.ext('onRequest', function (request, next) {
if (request.headers['x-forwarded-proto'] !== 'https') {
request.originalPath = request.path;
request.setUrl('/redirect');
}
next();
});
server.route([{
method: 'GET',
path: '/redirect',
handler: function (request, reply) {
var host = request.headers.host;
reply().redirect('https://' + host + request.originalPath);
}
}]);
}
Maybe someone can come up with something cleaner.
Warning: This does not prevent insecure http traffic. It just redirects the browsers to https locations.

Forwarding http to https in node.js express app using EBS & ELB environment

I am using the following to redirect all http requests to https requests.
I can see from logs that the header 'x-forwarded-proto' is never populated and is undefined.
app.get('*', function(req, res, next) {
//http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/TerminologyandKeyConcepts.html#x-forwarded-proto
if (req.headers['x-forwarded-proto'] != "https") {
res.redirect('https://' + req.get('host') + req.url);
} else {
next();
}
});
It is causing a redirect loop. How can I redirect properly without looping?
edit:
my original answer below is for express 3.x, for 4.x you can get a string http or https in req.protocol, thx #BrandonClark
use req.get, not req.headers. Note that POST requests and all other non-GET will not see this middleware.
It's also possible that Express does not carry the x-forwarded-proto header across when you redirect. You may need to set it yourself.
app.get('*', function(req, res, next) {
//http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/TerminologyandKeyConcepts.html#x-forwarded-proto
if (req.get('x-forwarded-proto') != "https") {
res.set('x-forwarded-proto', 'https');
res.redirect('https://' + req.get('host') + req.url);
} else {
next();
}
});
Another way to force https:
function ensureSecure(req, res, next){
if(req.secure){
// OK, continue
return next();
};
res.redirect('https://'+req.host+req.url); // handle port numbers if non 443
};
app.all('*', ensureSecure);
You can edit the nginx config file in the EC2 instance. SSH to ec2 instance and follow the following steps
go to /etc/nginx/conf.d
open 00_elastic_beanstalk_proxy.conf
sudo vi 00_elastic_beanstalk_proxy.conf
put
location / {
if ($http_x_forwarded_proto != 'https') {
rewrite ^ https://$host$request_uri? permanent;
}
…
}
reload nginx
sudo /usr/sbin/nginx -s reload

Resources