diff --git a/index.js b/index.js index 8432c2e..4a738a6 100644 --- a/index.js +++ b/index.js @@ -129,7 +129,12 @@ function Fetch(url, opts) { clearTimeout(reqTimeout); // handle redirect - if (self.isRedirect(res.statusCode)) { + if (self.isRedirect(res.statusCode) && options.redirect !== 'manual') { + if (options.redirect === 'error') { + reject(new FetchError('redirect mode is set to error: ' + options.url, 'no-redirect')); + return; + } + if (options.counter >= options.follow) { reject(new FetchError('maximum redirect reached at: ' + options.url, 'max-redirect')); return; @@ -169,6 +174,11 @@ function Fetch(url, opts) { } } + // normalize location header for manual redirect mode + if (options.redirect === 'manual') { + headers.set('location', resolve_url(options.url, headers.get('location'))); + } + // response object var output = new Response(body, { url: options.url diff --git a/lib/request.js b/lib/request.js index 8901090..37dbf82 100644 --- a/lib/request.js +++ b/lib/request.js @@ -44,6 +44,7 @@ function Request(input, init) { // fetch spec options this.method = init.method || input.method || 'GET'; + this.redirect = init.redirect || input.redirect || 'follow'; this.headers = new Headers(init.headers || input.headers || {}); this.url = url; diff --git a/test/test.js b/test/test.js index f12668f..fcb2758 100644 --- a/test/test.js +++ b/test/test.js @@ -89,7 +89,7 @@ describe('node-fetch', function() { url = 'http://localhost:50000/'; return expect(fetch(url)).to.eventually.be.rejected .and.be.an.instanceOf(FetchError) - .and.include({type: 'system', code: 'ECONNREFUSED', errno: 'ECONNREFUSED'}); + .and.include({ type: 'system', code: 'ECONNREFUSED', errno: 'ECONNREFUSED' }); }); it('should resolve into response', function() { @@ -298,6 +298,28 @@ describe('node-fetch', function() { .and.have.property('type', 'max-redirect'); }); + it('should support redirect mode, manual flag', function() { + url = base + '/redirect/301'; + opts = { + redirect: 'manual' + }; + return fetch(url, opts).then(function(res) { + expect(res.url).to.equal(base + '/redirect/301'); + expect(res.status).to.equal(301); + expect(res.headers.get('location')).to.equal(base + '/inspect'); + }); + }); + + it('should support redirect mode, error flag', function() { + url = base + '/redirect/301'; + opts = { + redirect: 'error' + }; + return expect(fetch(url, opts)).to.eventually.be.rejected + .and.be.an.instanceOf(FetchError) + .and.have.property('type', 'no-redirect'); + }); + it('should follow redirect code 301 and keep existing headers', function() { url = base + '/redirect/301'; opts = { @@ -1145,6 +1167,7 @@ describe('node-fetch', function() { var req = new Request(url, { body: body , method: 'POST' + , redirect: 'manual' , headers: { b: '2' } @@ -1155,6 +1178,7 @@ describe('node-fetch', function() { var cl = req.clone(); expect(cl.url).to.equal(url); expect(cl.method).to.equal('POST'); + expect(cl.redirect).to.equal('manual'); expect(cl.headers.get('b')).to.equal('2'); expect(cl.follow).to.equal(3); expect(cl.compress).to.equal(false);