node-fetch
Advanced tools
Comparing version 1.3.2 to 1.3.3
@@ -8,4 +8,11 @@ | ||
## v1.3.2 (master) | ||
## v1.3.3 (master) | ||
- Fix: make sure `Content-Length` header is set when body is string for POST/PUT/PATCH requests | ||
- Fix: handle body stream error, for cases such as incorrect `Content-Encoding` header | ||
- Fix: when following certain redirects, use `GET` on subsequent request per Fetch Spec | ||
- Fix: `Request` and `Response` constructors now parse headers input using `Headers` | ||
## v1.3.2 | ||
- Enhance: allow auto detect of form-data input (no `FormData` spec on node.js, this is form-data specific feature) | ||
@@ -12,0 +19,0 @@ |
19
index.js
@@ -85,2 +85,12 @@ | ||
// bring node-fetch closer to browser behavior by setting content-length automatically for POST, PUT, PATCH requests when body is empty or string | ||
if (!headers.has('content-length') && options.method.substr(0, 1).toUpperCase() === 'P') { | ||
if (typeof options.body === 'string') { | ||
headers.set('content-length', Buffer.byteLength(options.body)); | ||
// this is only necessary for older nodejs releases (before iojs merge) | ||
} else if (options.body === undefined || options.body === null) { | ||
headers.set('content-length', '0'); | ||
} | ||
} | ||
options.headers = headers.raw(); | ||
@@ -126,2 +136,11 @@ | ||
// per fetch spec, for POST request with 301/302 response, or any request with 303 response, use GET when following redirect | ||
if (res.statusCode === 303 | ||
|| ((res.statusCode === 301 || res.statusCode === 302) && options.method === 'POST')) | ||
{ | ||
options.method = 'GET'; | ||
delete options.body; | ||
delete options.headers['content-length']; | ||
} | ||
options.counter++; | ||
@@ -128,0 +147,0 @@ |
@@ -9,2 +9,3 @@ | ||
var parse_url = require('url').parse; | ||
var Headers = require('./headers'); | ||
@@ -46,3 +47,3 @@ module.exports = Request; | ||
this.method = init.method || input.method || 'GET'; | ||
this.headers = init.headers || input.headers || {}; | ||
this.headers = new Headers(init.headers || input.headers || {}); | ||
this.body = init.body || input.body; | ||
@@ -49,0 +50,0 @@ this.url = url; |
@@ -10,2 +10,3 @@ | ||
var convert = require('encoding').convert; | ||
var Headers = require('./headers'); | ||
@@ -23,6 +24,8 @@ module.exports = Response; | ||
opts = opts || {}; | ||
this.url = opts.url; | ||
this.status = opts.status; | ||
this.statusText = http.STATUS_CODES[this.status]; | ||
this.headers = opts.headers; | ||
this.headers = new Headers(opts.headers); | ||
this.body = body; | ||
@@ -89,2 +92,7 @@ this.bodyUsed = false; | ||
// handle stream error, such as incorrect content-encoding | ||
self.body.on('error', function(err) { | ||
reject(new Error('invalid response body at: ' + self.url + ' reason: ' + err.message)); | ||
}); | ||
self.body.on('data', function(chunk) { | ||
@@ -91,0 +99,0 @@ if (self._abort || chunk === null) { |
@@ -20,1 +20,3 @@ | ||
- There is currently no built-in caching, as server-side caching varies by use-cases. | ||
- Avoid using `Request` and `Response` constructors directly, as they are not spec-compliant yet (see open issues). |
{ | ||
"name": "node-fetch", | ||
"version": "1.3.2", | ||
"version": "1.3.3", | ||
"description": "A light-weight module that brings window.fetch to node.js and io.js", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -83,2 +83,9 @@ | ||
if (p === '/invalid-content-encoding') { | ||
res.statusCode = 200; | ||
res.setHeader('Content-Type', 'text/plain'); | ||
res.setHeader('Content-Encoding', 'gzip'); | ||
res.end('fake gzip string'); | ||
} | ||
if (p === '/timeout') { | ||
@@ -85,0 +92,0 @@ setTimeout(function() { |
@@ -228,2 +228,50 @@ | ||
it('should follow POST request redirect code 301 with GET', function() { | ||
url = base + '/redirect/301'; | ||
opts = { | ||
method: 'POST' | ||
, body: 'a=1' | ||
}; | ||
return fetch(url, opts).then(function(res) { | ||
expect(res.url).to.equal(base + '/inspect'); | ||
expect(res.status).to.equal(200); | ||
return res.json().then(function(result) { | ||
expect(result.method).to.equal('GET'); | ||
expect(result.body).to.equal(''); | ||
}); | ||
}); | ||
}); | ||
it('should follow POST request redirect code 302 with GET', function() { | ||
url = base + '/redirect/302'; | ||
opts = { | ||
method: 'POST' | ||
, body: 'a=1' | ||
}; | ||
return fetch(url, opts).then(function(res) { | ||
expect(res.url).to.equal(base + '/inspect'); | ||
expect(res.status).to.equal(200); | ||
return res.json().then(function(result) { | ||
expect(result.method).to.equal('GET'); | ||
expect(result.body).to.equal(''); | ||
}); | ||
}); | ||
}); | ||
it('should follow redirect code 303 with GET', function() { | ||
url = base + '/redirect/303'; | ||
opts = { | ||
method: 'PUT' | ||
, body: 'a=1' | ||
}; | ||
return fetch(url, opts).then(function(res) { | ||
expect(res.url).to.equal(base + '/inspect'); | ||
expect(res.status).to.equal(200); | ||
return res.json().then(function(result) { | ||
expect(result.method).to.equal('GET'); | ||
expect(result.body).to.equal(''); | ||
}); | ||
}); | ||
}); | ||
it('should obey maximum redirect', function() { | ||
@@ -352,2 +400,10 @@ url = base + '/redirect/chain'; | ||
it('should reject if response compression is invalid', function() { | ||
url = base + '/invalid-content-encoding'; | ||
return fetch(url).then(function(res) { | ||
expect(res.headers.get('content-type')).to.equal('text/plain'); | ||
return expect(res.text()).to.eventually.be.rejectedWith(Error); | ||
}); | ||
}); | ||
it('should allow disabling auto decompression', function() { | ||
@@ -421,2 +477,4 @@ url = base + '/gzip'; | ||
expect(res.method).to.equal('POST'); | ||
expect(res.headers['transfer-encoding']).to.be.undefined; | ||
expect(res.headers['content-length']).to.equal('0'); | ||
}); | ||
@@ -436,2 +494,4 @@ }); | ||
expect(res.body).to.equal('a=1'); | ||
expect(res.headers['transfer-encoding']).to.be.undefined; | ||
expect(res.headers['content-length']).to.equal('3'); | ||
}); | ||
@@ -451,2 +511,4 @@ }); | ||
expect(res.body).to.equal('a=1'); | ||
expect(res.headers['transfer-encoding']).to.equal('chunked'); | ||
expect(res.headers['content-length']).to.be.undefined; | ||
}); | ||
@@ -804,2 +866,36 @@ }); | ||
it('should support empty options in Response constructor', function() { | ||
var body = resumer().queue('a=1').end(); | ||
body = body.pipe(new stream.PassThrough()); | ||
var res = new Response(body); | ||
return res.text().then(function(result) { | ||
expect(result).to.equal('a=1'); | ||
}); | ||
}); | ||
it('should support parsing headers in Response constructor', function() { | ||
var body = resumer().queue('a=1').end(); | ||
body = body.pipe(new stream.PassThrough()); | ||
var res = new Response(body, { | ||
headers: { | ||
a: '1' | ||
} | ||
}); | ||
expect(res.headers.get('a')).to.equal('1'); | ||
return res.text().then(function(result) { | ||
expect(result).to.equal('a=1'); | ||
}); | ||
}); | ||
it('should support parsing headers in Request constructor', function() { | ||
url = base; | ||
var req = new Request(url, { | ||
headers: { | ||
a: '1' | ||
} | ||
}); | ||
expect(req.url).to.equal(url); | ||
expect(req.headers.get('a')).to.equal('1'); | ||
}); | ||
it('should support https request', function() { | ||
@@ -806,0 +902,0 @@ this.timeout(5000); |
Sorry, the diff of this file is not supported yet
55378
1517
82