From 0dae0a838d6afb719fff311b8de910d99a1655a2 Mon Sep 17 00:00:00 2001 From: Roland Warmerdam Date: Sun, 19 Jun 2016 06:30:10 -0700 Subject: [PATCH] Add redirect url to response object (#191) --- index.js | 31 ++++++++++++++++++------------- package.json | 2 +- readme.md | 4 ++++ test/redirects.js | 7 ++++++- 4 files changed, 29 insertions(+), 15 deletions(-) diff --git a/index.js b/index.js index ef3bfb3..9962f41 100644 --- a/index.js +++ b/index.js @@ -29,6 +29,7 @@ function requestAsEventEmitter(opts) { var ee = new EventEmitter(); var redirectCount = 0; var retryCount = 0; + var redirectUrl; var get = function (opts) { var fn = opts.protocol === 'https:' ? https : http; @@ -36,6 +37,10 @@ function requestAsEventEmitter(opts) { var req = fn.request(opts, function (res) { var statusCode = res.statusCode; + if (redirectUrl) { + res.url = redirectUrl; + } + if (isRedirect(statusCode) && opts.followRedirect && 'location' in res.headers && (opts.method === 'GET' || opts.method === 'HEAD')) { res.resume(); @@ -44,7 +49,7 @@ function requestAsEventEmitter(opts) { return; } - var redirectUrl = urlLib.resolve(urlLib.format(opts), res.headers.location); + redirectUrl = urlLib.resolve(urlLib.format(opts), res.headers.location); var redirectOpts = objectAssign({}, opts, urlLib.parse(redirectUrl)); ee.emit('redirect', res, redirectOpts); @@ -94,29 +99,29 @@ function asCallback(opts, cb) { }); ee.on('response', function (res) { - readAllStream(res, opts.encoding, function (err, data) { + readAllStream(res, opts.encoding, function (error, data) { var statusCode = res.statusCode; var limitStatusCode = opts.followRedirect ? 299 : 399; - if (err) { - cb(new got.ReadError(err, opts), null, res); + if (error) { + cb(new got.ReadError(error, opts), null, res); return; } if (statusCode < 200 || statusCode > limitStatusCode) { - err = new got.HTTPError(statusCode, opts); + error = new got.HTTPError(statusCode, opts); } if (opts.json && data) { try { data = parseJson(data); - } catch (e) { - e.fileName = urlLib.format(opts); - err = new got.ParseError(e, statusCode, opts); + } catch (err) { + err.fileName = urlLib.format(opts); + error = new got.ParseError(err, statusCode, opts); } } - cb(err, data, res); + cb(error, data, res); }); }); @@ -268,7 +273,7 @@ function normalizeArguments(url, opts) { opts.method = opts.method.toUpperCase(); if (opts.hostname === 'unix') { - var matches = /(.+)\:(.+)/.exec(opts.path); + var matches = /(.+):(.+)/.exec(opts.path); if (matches) { opts.socketPath = matches[1]; @@ -285,7 +290,7 @@ function normalizeArguments(url, opts) { } var noise = Math.random() * 100; - return (1 << iter) * 1000 + noise; + return ((1 << iter) * 1000) + noise; }; } @@ -309,8 +314,8 @@ function got(url, opts, cb) { try { return asPromise(normalizeArguments(url, opts)); - } catch (error) { - return PinkiePromise.reject(error); + } catch (err) { + return PinkiePromise.reject(err); } } diff --git a/package.json b/package.json index cc085e7..f0dba2e 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,7 @@ "pem": "^1.4.4", "pify": "^2.3.0", "tempfile": "^1.1.1", - "xo": "*" + "xo": "0.16.x" }, "xo": { "ignores": [ diff --git a/readme.md b/readme.md index 4009665..487ab44 100644 --- a/readme.md +++ b/readme.md @@ -60,6 +60,10 @@ It's a `GET` request by default, but can be changed in `options`. #### got(url, [options], [callback]) +Without `callback` argument returns a Promise, that resolves to `response` object with `body` property and a `url` property (which contains the final URL after redirects). + +Otherwise calls callback with `response` object (same as in previous case). + ##### url Type: `string`, `object` diff --git a/test/redirects.js b/test/redirects.js index 58967dc..e347b9d 100644 --- a/test/redirects.js +++ b/test/redirects.js @@ -87,6 +87,11 @@ test('redirects works with lowercase method', async t => { t.is(body, ''); }); -test.after('cleanup', async t => { +test('redirect response contains new url', async t => { + const url = (await got(`${s.url}/finite`)).url; + t.is(url, `${s.url}/`); +}); + +test.after('cleanup', async () => { await s.close(); });