Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Node.js www - non www redirection

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.

like image 988
Pono Avatar asked Aug 10 '11 15:08

Pono


4 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:

  1. Don't hardcode the http:// or https:// in the redirect URI; this makes life suck when switching between dev and prod environments - use req.protocol instead.
  2. 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 the trust proxy setting is enabled. This will ensure that req.protocol returns the protocol that the browser sees, not the protocol that finally made it to your app server.
  3. 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 like wwwgotcha.example.com.
  4. Be sure to use req.headers.host instead of req.host, as the latter strips out the port number. So, if you were to handle a request for www.example.com:3000, you'd redirect the user to www.example.com, minus the correct port number.
  5. 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.
  6. 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);
like image 125
jmar777 Avatar answered Nov 15 '22 23:11

jmar777


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();     
  }
})
like image 36
S M Avatar answered Nov 15 '22 23:11

S M


An updated version of jmar777's answer:

Using express

server.use((req, res, next) => {
  if (req.headers.host.startsWith('www.')) {
      const newHost = req.headers.host.slice(4)
      return res.redirect(
        301,
        `${req.protocol}://${newHost}${req.originalUrl}`,
      )
  }
  next()
})
like image 8
John Cido Avatar answered Nov 16 '22 00:11

John Cido


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');
like image 4
fe_lix_ Avatar answered Nov 15 '22 22:11

fe_lix_