Is there a chance to somehow redirect www to non-www URLs in node.js? Since there is no htaccess in node web server I am curious how to do that.
6 Answers
Even though this question is nearly 3 years old, there are a few subtle issues with the previously posted answers (and their comments), as well as some good advice in the comments that didn't make it back into the answers themselves. Here's a few important things to note:
- Don't hardcode the
http://
orhttps://
in the redirect URI; this makes life suck when switching between dev and prod environments - usereq.protocol
instead. - Also note that in order to use
req.protocol
reliably behind a proxy performing SSL termination (such as Elastic Load Balancer), you need to make sure that thetrust proxy
setting is enabled. This will ensure thatreq.protocol
returns the protocol that the browser sees, not the protocol that finally made it to your app server. - The accepted answer has a logic bug, as it matches on
/^www/
, but formats the redirect URI with/^www./
. In practice that probably won't bite anyone, but it would result in infinite redirect loops for something likewwwgotcha.example.com
. - Be sure to use
req.headers.host
instead ofreq.host
, as the latter strips out the port number. So, if you were to handle a request forwww.example.com:3000
, you'd redirect the user towww.example.com
, minus the correct port number. - As Dário pointed out, you'll typically want to use a 301 redirect when going from www to non-www (or vice versa) for SEO purposes.
- The last issue is the most minor, but it's generally safer to use
req.originalUrl
when creating redirect URIs, just in case you happen to be running in a mounted "sub app".
All that being said, here's my recommended approach that takes the above into consideration:
function wwwRedirect(req, res, next) {
if (req.headers.host.slice(0, 4) === 'www.') {
var newHost = req.headers.host.slice(4);
return res.redirect(301, req.protocol + '://' + newHost + req.originalUrl);
}
next();
};
app.set('trust proxy', true);
app.use(wwwRedirect);
-
1Thanks for the in depth answer. My question is, is node the place to do such redirects? I know nginx or Apache should normally take care of such things, but I can't shake the feeling that node really shouldn't be. Is there a way to set this on the DNS level? – James Spence Feb 27 '16 at 18:30
-
2@JamesSpence Good question. You wouldn't (couldn't) perform HTTP(S) and/or www redirects at the DNS level, but nginx is certainly an appropriate tool for the job. Nginx is also a valuable tool when it comes to a wide variety of attack mitigations, so I frankly don't leave home without it, so to speak. That being said, there's nothing fundamentally wrong with doing this in node-land, either, especially if you don't want to introduce a new reverse proxy into the mix that would otherwise would serve no purpose. – jmar777 Mar 01 '16 at 00:01
-
1Your answer is so useful and should be the accepted answer. Worked out of box! – Abk Dec 10 '18 at 18:12
You're using express, right? If so you can make a route handler that all GET requests go through, checks if they're to a 'www' URL, and redirects to the appropriate non-www URL if appropriate.
app.get('/*', function(req, res, next) {
if (req.headers.host.match(/^www/) !== null ) {
res.redirect('http://' + req.headers.host.replace(/^www\./, '') + req.url);
} else {
next();
}
})

- 8,155
- 3
- 35
- 36
-
9
-
2
-
3Also, make sure to set 301 as the first parameter of the redirect (by default, Express redirects are 302) – Vinch Aug 20 '13 at 15:20
-
6You can just use req.host: http://expressjs.com/api.html#req.host I also advise using req.protocol + '://' instead of hard-coding http:// – Kevin C. Nov 21 '13 at 18:16
-
1In addition to what @KevinC. stated, also be sure to `app.set('trust proxy', true);`. Otherwise if you're using, for example, Elastic Load Balancer to do SSL termination, you'll end up redirect https:// to http://. With `trust proxy` enabled, then `req.protocol` will represent the protocol used prior to hitting the proxy. – jmar777 May 22 '14 at 18:13
-
Oh, also the first regex should probably be `/^www\./` so that you don't get bit by weird corner cases like `wwwgotcha.example.com` resulting in an infinite redirect loop (since the regex used in the `.replace()` won't actually trim the `wwwgotcha` subdomain. – jmar777 May 22 '14 at 18:19
-
Argh, another thing: better to use `req.headers.host` (per the actual answer), vs. `req.host` as had also been suggested. The reason is that `req.host` strips the port number, so if you're not on the default :80 or :443 ports (e.g., express' default of :3000), you'll break the URL. – jmar777 May 22 '14 at 19:49
-
2Ok, last comment - I tried to summarize the various gotchas in a new answer (sorry for the comment spam!): http://stackoverflow.com/a/23816083/376789 – jmar777 May 22 '14 at 20:07
-
This is a basic exemple of how you could mimic the behavior of the redirect directive of apache in nodejs.
The function redirect takes either a RegExp or a string.
var http, redirect;
http = require("http");
redirect = function(host, res, pattern, redirect){
if (host == pattern || (pattern instanceof RegExp && host.match(pattern))) {
console.log("Redirected " + host);
res.writeHead(302, {
'location': redirect
});
res.end();
}};
http.createServer(function(req, res){
redirect(req.headers.host, res, /^www/, 'http://plouf.url');
redirect(req.headers.host, res, 'www.plouf.url', 'http://plouf.url');
res.writeHead(200, {
'Content-Type': 'text/plain'
});
res.end('Hello World\n');
}).listen(8000, '127.0.0.1');

- 938
- 11
- 18
-
Also, you should check this [question 4062260](http://stackoverflow.com/questions/4062260/nodejs-redirect-url). – fe_lix_ Aug 11 '11 at 08:06
In the world of DevOps and the increasing adoption of hosted platforms, this type of thing should never be handled by code. You should handle the redirect using infrastructure instead. Putting this code into the application means that issues cannot be mitigated by the Operations team should something fail in the apex entry. In addition, while it is fancy and shiny and hip, using the apex as your site url limits the ability of Operations to redirect the site should something go wrong and causes issues when you want to do a blue/green, A/B testing or geo-redirection (in some cases). Your code and app should be url-agnostic.

- 21
- 1
I agree with Sebastian above with a minor tweak and if you are using Express. I would just make it a middleware it will be processed on all requests.
function removeWWW(req, res, next){
if (req.headers.host.match(/^www/) !== null ) {
res.redirect('http://' + req.headers.host.replace(/^www\./, '') + req.url);
} else {
next();
}
}
app.use(removeWWW);

- 1
- 1