request: overwrite Content-Length if possible
Also reorganize header normalization
This commit is contained in:
parent
ac8ddaccb8
commit
11a9481405
|
@ -44,10 +44,6 @@ export default function fetch(url, opts) {
|
|||
throw new Error('only absolute urls are supported');
|
||||
}
|
||||
|
||||
if (options.protocol !== 'http:' && options.protocol !== 'https:') {
|
||||
throw new Error('only http(s) protocols are supported');
|
||||
}
|
||||
|
||||
const send = (options.protocol === 'https:' ? https : http).request;
|
||||
|
||||
// http.request only support string as host header, this hack make custom host header possible
|
||||
|
|
|
@ -57,7 +57,7 @@ export default class Request extends Body {
|
|||
});
|
||||
|
||||
// fetch spec options
|
||||
this.method = method;
|
||||
this.method = method.toUpperCase();
|
||||
this.redirect = init.redirect || input.redirect || 'follow';
|
||||
this.headers = new Headers(init.headers || input.headers || {});
|
||||
|
||||
|
@ -79,7 +79,6 @@ export default class Request extends Body {
|
|||
this.agent = init.agent || input.agent;
|
||||
|
||||
this[PARSED_URL] = parsedURL;
|
||||
|
||||
Object.defineProperty(this, Symbol.toStringTag, {
|
||||
value: 'Request',
|
||||
writable: false,
|
||||
|
@ -109,39 +108,53 @@ Object.defineProperty(Request.prototype, Symbol.toStringTag, {
|
|||
configurable: true
|
||||
});
|
||||
|
||||
function normalizeHeaders(request) {
|
||||
export function getNodeRequestOptions(request) {
|
||||
const headers = new Headers(request.headers);
|
||||
|
||||
if (request.compress) {
|
||||
headers.set('accept-encoding', 'gzip,deflate');
|
||||
// fetch step 3
|
||||
if (!headers.has('Accept')) {
|
||||
headers.set('Accept', '*/*');
|
||||
}
|
||||
|
||||
if (!headers.has('user-agent')) {
|
||||
headers.set('user-agent', 'node-fetch/1.0 (+https://github.com/bitinn/node-fetch)');
|
||||
// Basic fetch
|
||||
if (!/^https?:$/.test(request[PARSED_URL].protocol)) {
|
||||
throw new Error('only http(s) protocols are supported');
|
||||
}
|
||||
|
||||
if (!headers.has('connection') && !request.agent) {
|
||||
headers.set('connection', 'close');
|
||||
// HTTP-network-or-cache fetch steps 5-9
|
||||
let contentLengthValue = null;
|
||||
if (request.body == null && /^(POST|PUT)$/i.test(request.method)) {
|
||||
contentLengthValue = '0';
|
||||
}
|
||||
|
||||
if (!headers.has('accept')) {
|
||||
headers.set('accept', '*/*');
|
||||
}
|
||||
|
||||
if (!headers.has('content-length') && /post|put|patch|delete/i.test(request.method)) {
|
||||
if (request.body != null) {
|
||||
const totalBytes = getTotalBytes(request);
|
||||
if (typeof totalBytes === 'number') {
|
||||
headers.set('content-length', totalBytes);
|
||||
contentLengthValue = String(totalBytes);
|
||||
}
|
||||
}
|
||||
if (contentLengthValue) {
|
||||
headers.set('Content-Length', contentLengthValue);
|
||||
}
|
||||
|
||||
return headers;
|
||||
// HTTP-network-or-cache fetch step 12
|
||||
if (!headers.has('User-Agent')) {
|
||||
headers.set('User-Agent', 'node-fetch/1.0 (+https://github.com/bitinn/node-fetch)');
|
||||
}
|
||||
|
||||
export function getNodeRequestOptions(request) {
|
||||
// HTTP-network-or-cache fetch step 16
|
||||
if (request.compress) {
|
||||
headers.set('Accept-Encoding', 'gzip,deflate');
|
||||
}
|
||||
if (!headers.has('Connection') && !request.agent) {
|
||||
headers.set('Connection', 'close');
|
||||
}
|
||||
|
||||
// HTTP-network fetch step 4
|
||||
// chunked encoding is handled by Node.js
|
||||
|
||||
return Object.assign({}, request[PARSED_URL], {
|
||||
method: request.method,
|
||||
headers: normalizeHeaders(request).raw(),
|
||||
headers: headers.raw(),
|
||||
agent: request.agent
|
||||
});
|
||||
}
|
||||
|
|
37
test/test.js
37
test/test.js
|
@ -849,6 +849,27 @@ describe('node-fetch', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('should overwrite Content-Length if possible', function() {
|
||||
url = `${base}inspect`;
|
||||
// note that fetch simply calls tostring on an object
|
||||
opts = {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Length': '1000'
|
||||
},
|
||||
body: 'a=1'
|
||||
};
|
||||
return fetch(url, opts).then(res => {
|
||||
return res.json();
|
||||
}).then(res => {
|
||||
expect(res.method).to.equal('POST');
|
||||
expect(res.body).to.equal('a=1');
|
||||
expect(res.headers['transfer-encoding']).to.be.undefined;
|
||||
expect(res.headers['content-type']).to.equal('text/plain;charset=UTF-8');
|
||||
expect(res.headers['content-length']).to.equal('3');
|
||||
});
|
||||
});
|
||||
|
||||
it('should allow PUT request', function() {
|
||||
url = `${base}inspect`;
|
||||
opts = {
|
||||
|
@ -875,22 +896,6 @@ describe('node-fetch', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('should allow POST request with string body', function() {
|
||||
url = `${base}inspect`;
|
||||
opts = {
|
||||
method: 'POST'
|
||||
, body: 'a=1'
|
||||
};
|
||||
return fetch(url, opts).then(res => {
|
||||
return res.json();
|
||||
}).then(res => {
|
||||
expect(res.method).to.equal('POST');
|
||||
expect(res.body).to.equal('a=1');
|
||||
expect(res.headers['transfer-encoding']).to.be.undefined;
|
||||
expect(res.headers['content-length']).to.equal('3');
|
||||
});
|
||||
});
|
||||
|
||||
it('should allow DELETE request with string body', function() {
|
||||
url = `${base}inspect`;
|
||||
opts = {
|
||||
|
|
Loading…
Reference in New Issue