Handling a HTTP redirect in node.js

When making a HTTP request using node’s HTTP module (namely via the http.request() or http.get() methods), it’s possible to receive a status code which indicates a redirect to another URL (301, 302, 307). However unlike the browser’s XMLHttpRequest, node does not do the leg-work of automatically following the redirect and it’s something you have to handle yourself. Thankfully it’s not too hard to do at all.

var http = require('http');

http.get('http://example.com/a-page-which-redirects', function (res) {
    // Detect a redirect
    if (res.statusCode > 300 && res.statusCode < 400 && res.headers.location) {
        // The location for some (most) redirects will only contain the path,  not the hostname;
        // detect this and add the host to the path.
        if (url.parse(res.headers.location).hostname) {
              // Hostname included; make request to res.headers.location
        } else {
              // Hostname not included; get host from requested URL (url.parse()) and prepend to location.
        }

    // Otherwise no redirect; capture the response as normal            
    } else {
        var data = '';

        res.on('data', function (chunk) {
            data += chunk;
        }).on('end', function () {
            // Do something with 'data'
        });
    }
});

It’s important to realise that there’s nothing preventing the URL at res.headers.location redirecting to yet another URL (a re-redirect if you like), so you should consider having some form of loop to repeatedly follow redirect request until you reach an end.

However, this introduces another possible problem you need to be aware of; the infinite redirect loop which can occur if pages redirect between each other (possibly in-directly) infinitely. The HTTP 1.1 standard makes it clear it is the responsibility of the client to detect and handle such situations. It also notes that previous versions of this specification recommended a maximum of five redirections, so it would be a good idea to ensure your implementation allows at least 5 redirects before considering it an infinite loop.

If you’re now wishing there was something out there that did all this for you, look no further than the request module cooked up by mikeal.

var request = require('request');

request('http://example.com/a-page-which-redirects', function (error, response, body) {
    if (!error && response.statusCode === 200) {
        // Use body; no need to handle chunks of data *or* redirects!
    }
});

Links to further reading could include the documentation on the request module and a Stack Overflow post asking how redirects could be followed.