function download (u, httpOptions, redirects) {
return new Promise(function (resolve, reject) {
  u = url.parse(u);
  redirects = redirects || [];
  redirects.push(u.href);

  get(u, httpOptions)
    .then(function (res) {
      if (res.statusCode >= 400) {
        throw ono({ status: res.statusCode }, 'HTTP ERROR %d', res.statusCode);
      }
      else if (res.statusCode >= 300) {
        if (redirects.length > httpOptions.redirects) {
          reject(ono({ status: res.statusCode }, 'Error downloading %s. \nToo many redirects: \n  %s',
            redirects[0], redirects.join(' \n  ')));
        }
        else if (!res.headers.location) {
          throw ono({ status: res.statusCode }, 'HTTP %d redirect with no location header', res.statusCode);
        }
        else {
          debug('HTTP %d redirect %s -> %s', res.statusCode, u.href, res.headers.location);
          var redirectTo = url.resolve(u, res.headers.location);
          download(redirectTo, httpOptions, redirects).then(resolve, reject);
        }
      }
      else {
        resolve(res.body || new Buffer(0));
      }
    })
    .catch(function (err) {
      reject(ono(err, 'Error downloading', u.href));
    });
});
}
Downloads the given file.

@param {Url|string} u        - The url to download (can be a parsed {@link Url} object)
@param {object} httpOptions  - The `options.resolve.http` object
@param {number} [redirects]  - The redirect URLs that have already been followed

@returns {Promise<Buffer>}
The promise resolves with the raw downloaded data, or rejects if there is an HTTP error.