Socket
Socket
Sign inDemoInstall

node-fetch

Package Overview
Dependencies
Maintainers
2
Versions
96
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

node-fetch - npm Package Compare versions

Comparing version 2.0.0-alpha.3 to 2.0.0-alpha.4

50

CHANGELOG.md

@@ -8,30 +8,34 @@

## v2.0.0-alpha.3
## v2.0.0
- Major: overwrite user's `Content-Length` if we can be sure our information is correct
- Fix: exhaust list in `Headers` constructor before processing
This is a major release. Check [our upgrade guide](https://github.com/bitinn/node-fetch/blob/master/UPGRADE-GUIDE.md) for an overview on some key differences between v1 and v2.
## v2.0.0-alpha.2
### General changes
- Major: remove `headers.getAll()`; make `get()` return all headers delimited by commas (per spec)
- Major: remove undocumented `FOLLOW_SPEC` switch -- it is now the default
- Major: Node.js 0.10.x and 0.12.x support is dropped
- Major: `require('node-fetch/lib/response')` etc. is now unsupported; use `require('node-fetch').Response` or ES6 module imports
- Enhance: start testing on Node.js 4, 6, 7
- Enhance: use Rollup to produce a distributed bundle (less memory overhead and faster startup)
- Enhance: make `Object.prototype.toString()` on Headers, Requests, and Responses return correct class strings
- Other: rewrite in ES2015 using Babel
- Other: use Codecov for code coverage tracking
## v2.0.0-alpha.1
### HTTP requests
This is a major release. Check [our upgrade guide](https://github.com/bitinn/node-fetch/blob/master/UPGRADE-GUIDE.md) for an overview on some key differences between v1 and v2.
- Major: overwrite user's `Content-Length` if we can be sure our information is correct (per spec)
- Fix: support WHATWG URL objects, created by `whatwg-url` package or `require('url').URL` in Node.js 7+
- Major: Node.js 0.10.x support is dropped
- Major: rewrite in transpiled ES2015
### Response and Request classes
- Major: `response.text()` no longer attempts to detect encoding, instead always opting for UTF-8 (per spec); use `response.textConverted()` for the v1 behavior
- Major: make `response.json()` throw error instead of returning an empty object on 204 no-content respose (per spec; reverts behavior changed in v1.6.2)
- Major: internal methods are no longer exposed
- Major: throw error when a GET/HEAD Request is constructed with a non-null body (per spec)
- Major: `response.text()` no longer attempts to detect encoding, instead always opting for UTF-8 (per spec); use `response.textConverted()` for the old behavior
- Major: make `response.json()` throw error instead of returning an empty object on 204 no-content respose (per spec; reverts behavior set in v1.6.2)
- Major: arrays as parameters to `headers.append` and `headers.set` are joined as a string (per spec)
- Enhance: start testing on Node.js 4, 6, 7
- Enhance: use Rollup to produce a distributed bundle (less memory overhead and faster startup)
- Enhance: make `toString()` on Headers, Requests, and Responses return correct IDL class strings
- Enhance: add an option to conform to latest spec at the expense of reduced compatibility
- Enhance: set `Content-Length` header for Buffers as well
- Major: throw error when a `GET` or `HEAD` Request is constructed with a non-null body (per spec)
- Enhance: add `response.arrayBuffer()` (also applies to Requests)
- Enhance: add experimental `response.blob()` (also applies to Requests)
- Fix: fix Request and Response with `null` body
### Headers class
- Major: remove `headers.getAll()`; make `get()` return all headers delimited by commas (per spec)
- Enhance: make Headers iterable

@@ -41,7 +45,9 @@ - Enhance: make Headers constructor accept an array of tuples

- Fix: coerce Headers prototype function parameters to strings, where applicable
- Fix: fix Request and Response with `null` body
- Fix: support WHATWG URL objects, created by `whatwg-url` package or `require('url').URL` in Node.js 7+
- Other: use Codecov for code coverage tracking
### Documentation
- Enhance: more comprehensive API docs
- Enhance: add a list of default headers in README
# 1.x release

@@ -48,0 +54,0 @@

@@ -1,26 +0,8 @@

import _getIterator from 'babel-runtime/core-js/get-iterator';
import _Object$keys from 'babel-runtime/core-js/object/keys';
import { format, parse, resolve } from 'url';
import { STATUS_CODES } from 'http';
import * as http from 'http';
import * as https from 'https';
import { createGunzip, createInflate, createInflateRaw } from 'zlib';
import { Z_SYNC_FLUSH, createGunzip, createInflate, createInflateRaw } from 'zlib';
import * as zlib from 'zlib';
import { PassThrough } from 'stream';
import _Object$assign from 'babel-runtime/core-js/object/assign';
import _classCallCheck from 'babel-runtime/helpers/classCallCheck';
import _createClass from 'babel-runtime/helpers/createClass';
import _Symbol from 'babel-runtime/core-js/symbol';
import Stream, { PassThrough } from 'stream';
import { convert } from 'encoding';
import bodyStream from 'is-stream';
import toArrayBuffer from 'buffer-to-arraybuffer';
import _Symbol$toStringTag from 'babel-runtime/core-js/symbol/to-string-tag';
import _Object$defineProperty from 'babel-runtime/core-js/object/define-property';
import _Object$create from 'babel-runtime/core-js/object/create';
import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn';
import _inherits from 'babel-runtime/helpers/inherits';
import _Object$getPrototypeOf from 'babel-runtime/core-js/object/get-prototype-of';
import _Object$setPrototypeOf from 'babel-runtime/core-js/object/set-prototype-of';
import _Array$from from 'babel-runtime/core-js/array/from';
import _Symbol$iterator from 'babel-runtime/core-js/symbol/iterator';

@@ -30,11 +12,9 @@ // Based on https://github.com/tmpvar/jsdom/blob/aa85b2abf07766ff7bf5c1f6daafb3726f2f2db5/lib/jsdom/living/blob.js

var BUFFER = _Symbol('buffer');
var TYPE = _Symbol('type');
var CLOSED = _Symbol('closed');
const BUFFER = Symbol('buffer');
const TYPE = Symbol('type');
const CLOSED = Symbol('closed');
var Blob = function () {
function Blob() {
_classCallCheck(this, Blob);
_Object$defineProperty(this, _Symbol$toStringTag, {
class Blob {
constructor() {
Object.defineProperty(this, Symbol.toStringTag, {
value: 'Blob',

@@ -49,13 +29,13 @@ writable: false,

var blobParts = arguments[0];
var options = arguments[1];
const blobParts = arguments[0];
const options = arguments[1];
var buffers = [];
const buffers = [];
if (blobParts) {
var a = blobParts;
var length = Number(a.length);
for (var i = 0; i < length; i++) {
var element = a[i];
var buffer = void 0;
const a = blobParts;
const length = Number(a.length);
for (let i = 0; i < length; i++) {
const element = a[i];
let buffer;
if (element instanceof Buffer) {

@@ -78,3 +58,3 @@ buffer = element;

var type = options && options.type !== undefined && String(options.type).toLowerCase();
let type = options && options.type !== undefined && String(options.type).toLowerCase();
if (type && !/[^\u0020-\u007E]/.test(type)) {

@@ -84,10 +64,17 @@ this[TYPE] = type;

}
get size() {
return this[CLOSED] ? 0 : this[BUFFER].length;
}
get type() {
return this[TYPE];
}
get isClosed() {
return this[CLOSED];
}
slice() {
const size = this.size;
Blob.prototype.slice = function slice() {
var size = this.size;
var start = arguments[0];
var end = arguments[1];
var relativeStart = void 0,
relativeEnd = void 0;
const start = arguments[0];
const end = arguments[1];
let relativeStart, relativeEnd;
if (start === undefined) {

@@ -107,37 +94,17 @@ relativeStart = 0;

}
var span = Math.max(relativeEnd - relativeStart, 0);
const span = Math.max(relativeEnd - relativeStart, 0);
var buffer = this[BUFFER];
var slicedBuffer = buffer.slice(relativeStart, relativeStart + span);
var blob = new Blob([], { type: arguments[2] });
const buffer = this[BUFFER];
const slicedBuffer = buffer.slice(relativeStart, relativeStart + span);
const blob = new Blob([], { type: arguments[2] });
blob[BUFFER] = slicedBuffer;
blob[CLOSED] = this[CLOSED];
return blob;
};
Blob.prototype.close = function close() {
}
close() {
this[CLOSED] = true;
};
}
}
_createClass(Blob, [{
key: 'size',
get: function get() {
return this[CLOSED] ? 0 : this[BUFFER].length;
}
}, {
key: 'type',
get: function get() {
return this[TYPE];
}
}, {
key: 'isClosed',
get: function get() {
return this[CLOSED];
}
}]);
return Blob;
}();
_Object$defineProperty(Blob.prototype, _Symbol$toStringTag, {
Object.defineProperty(Blob.prototype, Symbol.toStringTag, {
value: 'BlobPrototype',

@@ -178,3 +145,3 @@ writable: false,

FetchError.prototype = _Object$create(Error.prototype);
FetchError.prototype = Object.create(Error.prototype);
FetchError.prototype.constructor = FetchError;

@@ -189,4 +156,3 @@ FetchError.prototype.name = 'FetchError';

var DISTURBED = _Symbol('disturbed');
var CONSUME_BODY = _Symbol('consumeBody');
const DISTURBED = Symbol('disturbed');

@@ -196,2 +162,4 @@ /**

*
* Cannot use ES6 class because Body must be called with .call().
*
* @param Stream body Readable stream

@@ -201,35 +169,37 @@ * @param Object opts Response options

*/
function Body(body) {
var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
_ref$size = _ref.size;
var Body = function () {
function Body(body) {
var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
_ref$size = _ref.size,
size = _ref$size === undefined ? 0 : _ref$size,
_ref$timeout = _ref.timeout,
timeout = _ref$timeout === undefined ? 0 : _ref$timeout;
let size = _ref$size === undefined ? 0 : _ref$size;
var _ref$timeout = _ref.timeout;
let timeout = _ref$timeout === undefined ? 0 : _ref$timeout;
_classCallCheck(this, Body);
if (body == null) {
// body is undefined or null
body = null;
} else if (typeof body === 'string') {
// body is string
} else if (body instanceof Blob) {
// body is blob
} else if (Buffer.isBuffer(body)) {
// body is buffer
} else if (bodyStream(body)) {
// body is stream
} else {
// none of the above
// coerce to string
body = String(body);
}
this.body = body;
this[DISTURBED] = false;
this.size = size;
this.timeout = timeout;
if (body == null) {
// body is undefined or null
body = null;
} else if (typeof body === 'string') {
// body is string
} else if (body instanceof Blob) {
// body is blob
} else if (Buffer.isBuffer(body)) {
// body is buffer
} else if (body instanceof Stream) {
// body is stream
} else {
// none of the above
// coerce to string
body = String(body);
}
this.body = body;
this[DISTURBED] = false;
this.size = size;
this.timeout = timeout;
}
Body.prototype = {
get bodyUsed() {
return this[DISTURBED];
},
/**

@@ -240,7 +210,7 @@ * Decode response as ArrayBuffer

*/
Body.prototype.arrayBuffer = function arrayBuffer() {
return this[CONSUME_BODY]().then(function (buf) {
return toArrayBuffer(buf);
arrayBuffer() {
return consumeBody.call(this).then(function (buf) {
return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
});
};
},

@@ -252,16 +222,14 @@ /**

*/
Body.prototype.blob = function blob() {
var ct = this.headers && this.headers.get('content-type') || '';
return this[CONSUME_BODY]().then(function (buf) {
var _Object$assign2;
return _Object$assign(
blob() {
let ct = this.headers && this.headers.get('content-type') || '';
return consumeBody.call(this).then(function (buf) {
return Object.assign(
// Prevent copying
new Blob([], {
type: ct.toLowerCase()
}), (_Object$assign2 = {}, _Object$assign2[BUFFER] = buf, _Object$assign2));
}), {
[BUFFER]: buf
});
});
};
},

@@ -273,9 +241,7 @@ /**

*/
Body.prototype.json = function json() {
return this[CONSUME_BODY]().then(function (buffer) {
json() {
return consumeBody.call(this).then(function (buffer) {
return JSON.parse(buffer.toString());
});
};
},

@@ -287,9 +253,7 @@ /**

*/
Body.prototype.text = function text() {
return this[CONSUME_BODY]().then(function (buffer) {
text() {
return consumeBody.call(this).then(function (buffer) {
return buffer.toString();
});
};
},

@@ -301,8 +265,6 @@ /**

*/
buffer() {
return consumeBody.call(this);
},
Body.prototype.buffer = function buffer() {
return this[CONSUME_BODY]();
};
/**

@@ -314,116 +276,121 @@ * Decode response as text, while automatically detecting the encoding and

*/
Body.prototype.textConverted = function textConverted() {
textConverted() {
var _this = this;
return this[CONSUME_BODY]().then(function (buffer) {
return consumeBody.call(this).then(function (buffer) {
return convertBody(buffer, _this.headers);
});
};
}
/**
* Decode buffers into utf-8 string
*
* @return Promise
*/
};
Body.prototype[CONSUME_BODY] = function () {
var _this2 = this;
if (this[DISTURBED]) {
return Body.Promise.reject(new Error('body used already for: ' + this.url));
Body.mixIn = function (proto) {
for (const name of Object.getOwnPropertyNames(Body.prototype)) {
// istanbul ignore else: future proof
if (!(name in proto)) {
const desc = Object.getOwnPropertyDescriptor(Body.prototype, name);
Object.defineProperty(proto, name, desc);
}
}
};
this[DISTURBED] = true;
/**
* Decode buffers into utf-8 string
*
* @return Promise
*/
function consumeBody(body) {
var _this2 = this;
// body is null
if (this.body === null) {
return Body.Promise.resolve(new Buffer(0));
}
if (this[DISTURBED]) {
return Body.Promise.reject(new Error(`body used already for: ${this.url}`));
}
// body is string
if (typeof this.body === 'string') {
return Body.Promise.resolve(new Buffer(this.body));
}
this[DISTURBED] = true;
// body is blob
if (this.body instanceof Blob) {
return Body.Promise.resolve(this.body[BUFFER]);
}
// body is null
if (this.body === null) {
return Body.Promise.resolve(new Buffer(0));
}
// body is buffer
if (Buffer.isBuffer(this.body)) {
return Body.Promise.resolve(this.body);
}
// body is string
if (typeof this.body === 'string') {
return Body.Promise.resolve(new Buffer(this.body));
}
// istanbul ignore if: should never happen
if (!bodyStream(this.body)) {
return Body.Promise.resolve(new Buffer(0));
}
// body is blob
if (this.body instanceof Blob) {
return Body.Promise.resolve(this.body[BUFFER]);
}
// body is stream
// get ready to actually consume the body
var accum = [];
var accumBytes = 0;
var abort = false;
// body is buffer
if (Buffer.isBuffer(this.body)) {
return Body.Promise.resolve(this.body);
}
return new Body.Promise(function (resolve$$1, reject) {
var resTimeout = void 0;
// istanbul ignore if: should never happen
if (!(this.body instanceof Stream)) {
return Body.Promise.resolve(new Buffer(0));
}
// allow timeout on slow response body
if (_this2.timeout) {
resTimeout = setTimeout(function () {
abort = true;
reject(new FetchError('Response timeout while trying to fetch ' + _this2.url + ' (over ' + _this2.timeout + 'ms)', 'body-timeout'));
}, _this2.timeout);
}
// body is stream
// get ready to actually consume the body
let accum = [];
let accumBytes = 0;
let abort = false;
// handle stream error, such as incorrect content-encoding
_this2.body.on('error', function (err) {
reject(new FetchError('Invalid response body while trying to fetch ' + _this2.url + ': ' + err.message, 'system', err));
});
return new Body.Promise(function (resolve$$1, reject) {
let resTimeout;
_this2.body.on('data', function (chunk) {
if (abort || chunk === null) {
return;
}
// allow timeout on slow response body
if (_this2.timeout) {
resTimeout = setTimeout(function () {
abort = true;
reject(new FetchError(`Response timeout while trying to fetch ${_this2.url} (over ${_this2.timeout}ms)`, 'body-timeout'));
}, _this2.timeout);
}
if (_this2.size && accumBytes + chunk.length > _this2.size) {
abort = true;
reject(new FetchError('content size at ' + _this2.url + ' over limit: ' + _this2.size, 'max-size'));
return;
}
// handle stream error, such as incorrect content-encoding
_this2.body.on('error', function (err) {
reject(new FetchError(`Invalid response body while trying to fetch ${_this2.url}: ${err.message}`, 'system', err));
});
accumBytes += chunk.length;
accum.push(chunk);
});
_this2.body.on('data', function (chunk) {
if (abort || chunk === null) {
return;
}
_this2.body.on('end', function () {
if (abort) {
return;
}
if (_this2.size && accumBytes + chunk.length > _this2.size) {
abort = true;
reject(new FetchError(`content size at ${_this2.url} over limit: ${_this2.size}`, 'max-size'));
return;
}
clearTimeout(resTimeout);
resolve$$1(Buffer.concat(accum));
});
accumBytes += chunk.length;
accum.push(chunk);
});
};
_createClass(Body, [{
key: 'bodyUsed',
get: function get() {
return this[DISTURBED];
}
}]);
_this2.body.on('end', function () {
if (abort) {
return;
}
return Body;
}();
clearTimeout(resTimeout);
resolve$$1(Buffer.concat(accum));
});
});
}
/**
* Detect buffer encoding and convert to target encoding
* ref: http://www.w3.org/TR/2011/WD-html5-20110113/parsing.html#determining-the-character-encoding
*
* @param Buffer buffer Incoming buffer
* @param String encoding Target encoding
* @return String
*/
function convertBody(buffer, headers) {
var ct = headers.get('content-type');
var charset = 'utf-8';
var res = void 0,
str = void 0;
const ct = headers.get('content-type');
let charset = 'utf-8';
let res, str;

@@ -478,6 +445,5 @@ // header

*/
function clone$1(instance) {
var p1 = void 0,
p2 = void 0;
var body = instance.body;
function clone(instance) {
let p1, p2;
let body = instance.body;

@@ -491,3 +457,3 @@ // don't allow cloning a used body

// note: we can't clone the form-data object without having it as a dependency
if (bodyStream(body) && typeof body.getBoundary !== 'function') {
if (body instanceof Stream && typeof body.getBoundary !== 'function') {
// tee instance body

@@ -516,3 +482,3 @@ p1 = new PassThrough();

function extractContentType(instance) {
var body = instance.body;
const body = instance.body;

@@ -536,3 +502,3 @@ // istanbul ignore if: Currently, because of a guard in Request, body

// detect form data input from form-data module
return 'multipart/form-data;boundary=' + body.getBoundary();
return `multipart/form-data;boundary=${body.getBoundary()}`;
} else {

@@ -546,4 +512,5 @@ // body is stream

function getTotalBytes(instance) {
var body = instance.body;
const body = instance.body;
// istanbul ignore if: included for completion

@@ -578,3 +545,3 @@ if (body === null) {

function writeToStream(dest, instance) {
var body = instance.body;
const body = instance.body;

@@ -651,3 +618,3 @@

if (!isValidTokenChar(val.charCodeAt(0))) return false;
var len = val.length;
const len = val.length;
if (len > 1) {

@@ -705,3 +672,3 @@ if (!isValidTokenChar(val.charCodeAt(1))) return false;

if (!checkIsHttpToken(name)) {
throw new TypeError(name + ' is not a legal HTTP header name');
throw new TypeError(`${name} is not a legal HTTP header name`);
}

@@ -714,3 +681,3 @@ return name.toLowerCase();

if (checkInvalidHeaderChar(value)) {
throw new TypeError(value + ' is not a legal HTTP header value');
throw new TypeError(`${value} is not a legal HTTP header value`);
}

@@ -720,5 +687,4 @@ return value;

var MAP = _Symbol('map');
var Headers = function () {
const MAP = Symbol('map');
class Headers {
/**

@@ -730,9 +696,20 @@ * Headers class

*/
function Headers() {
var init = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : undefined;
constructor() {
let init = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : undefined;
_classCallCheck(this, Headers);
this[MAP] = Object.create(null);
this[MAP] = _Object$create(null);
if (init instanceof Headers) {
const rawHeaders = init.raw();
const headerNames = Object.keys(rawHeaders);
for (const headerName of headerNames) {
for (const value of rawHeaders[headerName]) {
this.append(headerName, value);
}
}
return;
}
// We don't worry about converting prop to ByteString here as append()

@@ -743,3 +720,3 @@ // will handle it.

} else if (typeof init === 'object') {
var method = init[_Symbol$iterator];
const method = init[Symbol.iterator];
if (method != null) {

@@ -752,59 +729,20 @@ if (typeof method !== 'function') {

// Note: per spec we have to first exhaust the lists then process them
var pairs = [];
for (var _iterator = init, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _getIterator(_iterator);;) {
var _ref;
if (_isArray) {
if (_i >= _iterator.length) break;
_ref = _iterator[_i++];
} else {
_i = _iterator.next();
if (_i.done) break;
_ref = _i.value;
}
var pair = _ref;
if (typeof pair !== 'object' || typeof pair[_Symbol$iterator] !== 'function') {
const pairs = [];
for (const pair of init) {
if (typeof pair !== 'object' || typeof pair[Symbol.iterator] !== 'function') {
throw new TypeError('Each header pair must be iterable');
}
pairs.push(_Array$from(pair));
pairs.push(Array.from(pair));
}
for (var _iterator2 = pairs, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _getIterator(_iterator2);;) {
var _ref2;
if (_isArray2) {
if (_i2 >= _iterator2.length) break;
_ref2 = _iterator2[_i2++];
} else {
_i2 = _iterator2.next();
if (_i2.done) break;
_ref2 = _i2.value;
}
var _pair = _ref2;
if (_pair.length !== 2) {
for (const pair of pairs) {
if (pair.length !== 2) {
throw new TypeError('Each header pair must be a name/value tuple');
}
this.append(_pair[0], _pair[1]);
this.append(pair[0], pair[1]);
}
} else {
// record<ByteString, ByteString>
for (var _iterator3 = _Object$keys(init), _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _getIterator(_iterator3);;) {
var _ref3;
if (_isArray3) {
if (_i3 >= _iterator3.length) break;
_ref3 = _iterator3[_i3++];
} else {
_i3 = _iterator3.next();
if (_i3.done) break;
_ref3 = _i3.value;
}
var key = _ref3;
var value = init[key];
for (const key of Object.keys(init)) {
const value = init[key];
this.append(key, value);

@@ -817,3 +755,3 @@ }

_Object$defineProperty(this, _Symbol$toStringTag, {
Object.defineProperty(this, Symbol.toStringTag, {
value: 'Headers',

@@ -832,6 +770,4 @@ writable: false,

*/
Headers.prototype.get = function get(name) {
var list = this[MAP][sanitizeName(name)];
get(name) {
const list = this[MAP][sanitizeName(name)];
if (!list) {

@@ -841,4 +777,4 @@ return null;

return list.join(',');
};
return list.join(', ');
}

@@ -852,13 +788,11 @@ /**

*/
forEach(callback) {
let thisArg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined;
Headers.prototype.forEach = function forEach(callback) {
var thisArg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined;
var pairs = getHeaderPairs(this);
var i = 0;
let pairs = getHeaderPairs(this);
let i = 0;
while (i < pairs.length) {
var _pairs$i = pairs[i],
name = _pairs$i[0],
value = _pairs$i[1];
var _pairs$i = pairs[i];
const name = _pairs$i[0],
value = _pairs$i[1];

@@ -869,3 +803,3 @@ callback.call(thisArg, value, name, this);

}
};
}

@@ -879,7 +813,5 @@ /**

*/
Headers.prototype.set = function set(name, value) {
set(name, value) {
this[MAP][sanitizeName(name)] = [sanitizeValue(value)];
};
}

@@ -893,5 +825,3 @@ /**

*/
Headers.prototype.append = function append(name, value) {
append(name, value) {
if (!this.has(name)) {

@@ -903,3 +833,3 @@ this.set(name, value);

this[MAP][sanitizeName(name)].push(sanitizeValue(value));
};
}

@@ -912,7 +842,5 @@ /**

*/
Headers.prototype.has = function has(name) {
has(name) {
return !!this[MAP][sanitizeName(name)];
};
}

@@ -925,7 +853,5 @@ /**

*/
Headers.prototype.delete = function _delete(name) {
delete(name) {
delete this[MAP][sanitizeName(name)];
};
}

@@ -937,5 +863,5 @@ /**

*/
Headers.prototype.raw = function raw() {
raw() {
return this[MAP];
};
}

@@ -947,7 +873,5 @@ /**

*/
Headers.prototype.keys = function keys() {
keys() {
return createHeadersIterator(this, 'key');
};
}

@@ -959,7 +883,5 @@ /**

*/
Headers.prototype.values = function values() {
values() {
return createHeadersIterator(this, 'value');
};
}

@@ -973,14 +895,9 @@ /**

*/
Headers.prototype[_Symbol$iterator] = function () {
[Symbol.iterator]() {
return createHeadersIterator(this, 'key+value');
};
}
}
Headers.prototype.entries = Headers.prototype[Symbol.iterator];
return Headers;
}();
Headers.prototype.entries = Headers.prototype[_Symbol$iterator];
_Object$defineProperty(Headers.prototype, _Symbol$toStringTag, {
Object.defineProperty(Headers.prototype, Symbol.toStringTag, {
value: 'HeadersPrototype',

@@ -993,3 +910,3 @@ writable: false,

function getHeaderPairs(headers, kind) {
var keys = _Object$keys(headers[MAP]).sort();
const keys = Object.keys(headers[MAP]).sort();
return keys.map(kind === 'key' ? function (k) {

@@ -1002,9 +919,9 @@ return [k];

var INTERNAL = _Symbol('internal');
const INTERNAL = Symbol('internal');
function createHeadersIterator(target, kind) {
var iterator = _Object$create(HeadersIteratorPrototype);
const iterator = Object.create(HeadersIteratorPrototype);
iterator[INTERNAL] = {
target: target,
kind: kind,
target,
kind,
index: 0

@@ -1015,16 +932,16 @@ };

var HeadersIteratorPrototype = _Object$setPrototypeOf({
next: function next() {
const HeadersIteratorPrototype = Object.setPrototypeOf({
next() {
// istanbul ignore if
if (!this || _Object$getPrototypeOf(this) !== HeadersIteratorPrototype) {
if (!this || Object.getPrototypeOf(this) !== HeadersIteratorPrototype) {
throw new TypeError('Value of `this` is not a HeadersIterator');
}
var _INTERNAL = this[INTERNAL],
target = _INTERNAL.target,
kind = _INTERNAL.kind,
index = _INTERNAL.index;
var _INTERNAL = this[INTERNAL];
const target = _INTERNAL.target,
kind = _INTERNAL.kind,
index = _INTERNAL.index;
var values = getHeaderPairs(target, kind);
var len = values.length;
const values = getHeaderPairs(target, kind);
const len = values.length;
if (index >= len) {

@@ -1037,6 +954,6 @@ return {

var pair = values[index];
const pair = values[index];
this[INTERNAL].index = index + 1;
var result = void 0;
let result;
if (kind === 'key') {

@@ -1055,12 +972,5 @@ result = pair[0];

}
}, _Object$getPrototypeOf(_Object$getPrototypeOf(_getIterator([]))));
}, Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]())));
// On Node.js v0.12 the %IteratorPrototype% object is broken
if (typeof HeadersIteratorPrototype[_Symbol$iterator] !== 'function') {
HeadersIteratorPrototype[_Symbol$iterator] = function () {
return this;
};
}
_Object$defineProperty(HeadersIteratorPrototype, _Symbol$toStringTag, {
Object.defineProperty(HeadersIteratorPrototype, Symbol.toStringTag, {
value: 'HeadersIterator',

@@ -1085,20 +995,16 @@ writable: false,

*/
class Response {
constructor() {
let body = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
let opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var Response = function (_Body) {
_inherits(Response, _Body);
Body.call(this, body, opts);
function Response() {
var body = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
this.url = opts.url;
this.status = opts.status || 200;
this.statusText = opts.statusText || STATUS_CODES[this.status];
_classCallCheck(this, Response);
this.headers = new Headers(opts.headers);
var _this = _possibleConstructorReturn(this, _Body.call(this, body, opts));
_this.url = opts.url;
_this.status = opts.status || 200;
_this.statusText = opts.statusText || STATUS_CODES[_this.status];
_this.headers = new Headers(opts.headers);
_Object$defineProperty(_this, _Symbol$toStringTag, {
Object.defineProperty(this, Symbol.toStringTag, {
value: 'Response',

@@ -1109,3 +1015,2 @@ writable: false,

});
return _this;
}

@@ -1116,4 +1021,6 @@

*/
get ok() {
return this.status >= 200 && this.status < 300;
}
/**

@@ -1124,5 +1031,5 @@ * Clone this response

*/
Response.prototype.clone = function clone() {
clone() {
return new Response(clone$1(this), {
return new Response(clone(this), {
url: this.url,

@@ -1134,15 +1041,8 @@ status: this.status,

});
};
}
}
_createClass(Response, [{
key: 'ok',
get: function get() {
return this.status >= 200 && this.status < 300;
}
}]);
Body.mixIn(Response.prototype);
return Response;
}(Body);
_Object$defineProperty(Response.prototype, _Symbol$toStringTag, {
Object.defineProperty(Response.prototype, Symbol.toStringTag, {
value: 'ResponsePrototype',

@@ -1160,3 +1060,3 @@ writable: false,

var PARSED_URL = _Symbol('url');
const PARSED_URL = Symbol('url');

@@ -1170,13 +1070,8 @@ /**

*/
class Request {
constructor(input) {
let init = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var Request = function (_Body) {
_inherits(Request, _Body);
let parsedURL;
function Request(input) {
var init = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
_classCallCheck(this, Request);
var parsedURL = void 0;
// normalize input

@@ -1191,3 +1086,3 @@ if (!(input instanceof Request)) {

// coerce input to a string before attempting to parse
parsedURL = parse('' + input);
parsedURL = parse(`${input}`);
}

@@ -1199,3 +1094,3 @@ input = {};

var method = init.method || input.method || 'GET';
let method = init.method || input.method || 'GET';

@@ -1206,18 +1101,18 @@ if ((init.body != null || input instanceof Request && input.body !== null) && (method === 'GET' || method === 'HEAD')) {

var inputBody = init.body != null ? init.body : input instanceof Request && input.body !== null ? clone$1(input) : null;
let inputBody = init.body != null ? init.body : input instanceof Request && input.body !== null ? clone(input) : null;
// fetch spec options
var _this = _possibleConstructorReturn(this, _Body.call(this, inputBody, {
Body.call(this, inputBody, {
timeout: init.timeout || input.timeout || 0,
size: init.size || input.size || 0
}));
});
_this.method = method.toUpperCase();
_this.redirect = init.redirect || input.redirect || 'follow';
_this.headers = new Headers(init.headers || input.headers || {});
// fetch spec options
this.method = method.toUpperCase();
this.redirect = init.redirect || input.redirect || 'follow';
this.headers = new Headers(init.headers || input.headers || {});
if (init.body != null) {
var contentType = extractContentType(_this);
if (contentType !== null && !_this.headers.has('Content-Type')) {
_this.headers.append('Content-Type', contentType);
const contentType = extractContentType(this);
if (contentType !== null && !this.headers.has('Content-Type')) {
this.headers.append('Content-Type', contentType);
}

@@ -1227,9 +1122,9 @@ }

// server only options
_this.follow = init.follow !== undefined ? init.follow : input.follow !== undefined ? input.follow : 20;
_this.compress = init.compress !== undefined ? init.compress : input.compress !== undefined ? input.compress : true;
_this.counter = init.counter || input.counter || 0;
_this.agent = init.agent || input.agent;
this.follow = init.follow !== undefined ? init.follow : input.follow !== undefined ? input.follow : 20;
this.compress = init.compress !== undefined ? init.compress : input.compress !== undefined ? input.compress : true;
this.counter = init.counter || input.counter || 0;
this.agent = init.agent || input.agent;
_this[PARSED_URL] = parsedURL;
_Object$defineProperty(_this, _Symbol$toStringTag, {
this[PARSED_URL] = parsedURL;
Object.defineProperty(this, Symbol.toStringTag, {
value: 'Request',

@@ -1240,5 +1135,8 @@ writable: false,

});
return _this;
}
get url() {
return format(this[PARSED_URL]);
}
/**

@@ -1249,17 +1147,10 @@ * Clone this request

*/
Request.prototype.clone = function clone$1() {
clone() {
return new Request(this);
};
}
}
_createClass(Request, [{
key: 'url',
get: function get() {
return format(this[PARSED_URL]);
}
}]);
Body.mixIn(Request.prototype);
return Request;
}(Body);
_Object$defineProperty(Request.prototype, _Symbol$toStringTag, {
Object.defineProperty(Request.prototype, Symbol.toStringTag, {
value: 'RequestPrototype',

@@ -1272,3 +1163,4 @@ writable: false,

function getNodeRequestOptions(request) {
var headers = new Headers(request.headers);
const parsedURL = request[PARSED_URL];
const headers = new Headers(request.headers);

@@ -1281,8 +1173,12 @@ // fetch step 3

// Basic fetch
if (!/^https?:$/.test(request[PARSED_URL].protocol)) {
throw new Error('only http(s) protocols are supported');
if (!parsedURL.protocol || !parsedURL.hostname) {
throw new TypeError('Only absolute URLs are supported');
}
if (!/^https?:$/.test(parsedURL.protocol)) {
throw new TypeError('Only HTTP(S) protocols are supported');
}
// HTTP-network-or-cache fetch steps 5-9
var contentLengthValue = null;
let contentLengthValue = null;
if (request.body == null && /^(POST|PUT)$/i.test(request.method)) {

@@ -1292,3 +1188,3 @@ contentLengthValue = '0';

if (request.body != null) {
var totalBytes = getTotalBytes(request);
const totalBytes = getTotalBytes(request);
if (typeof totalBytes === 'number') {

@@ -1318,3 +1214,3 @@ contentLengthValue = String(totalBytes);

return _Object$assign({}, request[PARSED_URL], {
return Object.assign({}, parsedURL, {
method: request.method,

@@ -1351,12 +1247,7 @@ headers: headers.raw(),

// build request object
var request = new Request(url$$1, opts);
const request = new Request(url$$1, opts);
const options = getNodeRequestOptions(request);
var options = getNodeRequestOptions(request);
const send = (options.protocol === 'https:' ? https : http).request;
if (!options.protocol || !options.hostname) {
throw new Error('only absolute urls are supported');
}
var send = (options.protocol === 'https:' ? https : http).request;
// http.request only support string as host header, this hack make custom host header possible

@@ -1368,4 +1259,4 @@ if (options.headers.host) {

// send request
var req = send(options);
var reqTimeout = void 0;
const req = send(options);
let reqTimeout;

@@ -1376,3 +1267,3 @@ if (request.timeout) {

req.abort();
reject(new FetchError('network timeout at: ' + request.url, 'request-timeout'));
reject(new FetchError(`network timeout at: ${request.url}`, 'request-timeout'));
}, request.timeout);

@@ -1384,3 +1275,3 @@ });

clearTimeout(reqTimeout);
reject(new FetchError('request to ' + request.url + ' failed, reason: ' + err.message, 'system', err));
reject(new FetchError(`request to ${request.url} failed, reason: ${err.message}`, 'system', err));
});

@@ -1394,3 +1285,3 @@

if (request.redirect === 'error') {
reject(new FetchError('redirect mode is set to error: ' + request.url, 'no-redirect'));
reject(new FetchError(`redirect mode is set to error: ${request.url}`, 'no-redirect'));
return;

@@ -1400,3 +1291,3 @@ }

if (request.counter >= request.follow) {
reject(new FetchError('maximum redirect reached at: ' + request.url, 'max-redirect'));
reject(new FetchError(`maximum redirect reached at: ${request.url}`, 'max-redirect'));
return;

@@ -1406,3 +1297,3 @@ }

if (!res.headers.location) {
reject(new FetchError('redirect location header missing at: ' + request.url, 'invalid-redirect'));
reject(new FetchError(`redirect location header missing at: ${request.url}`, 'invalid-redirect'));
return;

@@ -1425,36 +1316,10 @@ }

// normalize location header for manual redirect mode
var headers = new Headers();
for (var _iterator = _Object$keys(res.headers), _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _getIterator(_iterator);;) {
var _ref;
if (_isArray) {
if (_i >= _iterator.length) break;
_ref = _iterator[_i++];
} else {
_i = _iterator.next();
if (_i.done) break;
_ref = _i.value;
}
var _name = _ref;
if (Array.isArray(res.headers[_name])) {
for (var _iterator2 = res.headers[_name], _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _getIterator(_iterator2);;) {
var _ref2;
if (_isArray2) {
if (_i2 >= _iterator2.length) break;
_ref2 = _iterator2[_i2++];
} else {
_i2 = _iterator2.next();
if (_i2.done) break;
_ref2 = _i2.value;
}
var val = _ref2;
headers.append(_name, val);
const headers = new Headers();
for (const name of Object.keys(res.headers)) {
if (Array.isArray(res.headers[name])) {
for (const val of res.headers[name]) {
headers.append(name, val);
}
} else {
headers.append(_name, res.headers[_name]);
headers.append(name, res.headers[name]);
}

@@ -1467,4 +1332,4 @@ }

// prepare response
var body = res.pipe(new PassThrough());
var response_options = {
let body = res.pipe(new PassThrough());
const response_options = {
url: request.url,

@@ -1478,32 +1343,40 @@ status: res.statusCode,

// response object
var output = void 0;
// HTTP-network fetch step 16.1.2
const codings = headers.get('Content-Encoding');
// HTTP-network fetch step 16.1.3: handle content codings
// in following scenarios we ignore compression support
// 1. compression support is disabled
// 2. HEAD request
// 3. no content-encoding header
// 3. no Content-Encoding header
// 4. no content response (204)
// 5. content not modified response (304)
if (!request.compress || request.method === 'HEAD' || !headers.has('content-encoding') || res.statusCode === 204 || res.statusCode === 304) {
output = new Response(body, response_options);
resolve$$1(output);
if (!request.compress || request.method === 'HEAD' || codings === null || res.statusCode === 204 || res.statusCode === 304) {
resolve$$1(new Response(body, response_options));
return;
}
// otherwise, check for gzip or deflate
var name = headers.get('content-encoding');
// For Node v6+
// Be less strict when decoding compressed responses, since sometimes
// servers send slightly invalid responses that are still accepted
// by common browsers.
// Always using Z_SYNC_FLUSH is what cURL does.
const zlibOptions = {
flush: Z_SYNC_FLUSH,
finishFlush: Z_SYNC_FLUSH
};
// for gzip
if (name == 'gzip' || name == 'x-gzip') {
body = body.pipe(createGunzip());
output = new Response(body, response_options);
resolve$$1(output);
if (codings == 'gzip' || codings == 'x-gzip') {
body = body.pipe(createGunzip(zlibOptions));
resolve$$1(new Response(body, response_options));
return;
}
// for deflate
} else if (name == 'deflate' || name == 'x-deflate') {
// for deflate
if (codings == 'deflate' || codings == 'x-deflate') {
// handle the infamous raw deflate response from old servers
// a hack for old IIS and Apache servers
var raw = res.pipe(new PassThrough());
const raw = res.pipe(new PassThrough());
raw.once('data', function (chunk) {

@@ -1516,4 +1389,3 @@ // see http://stackoverflow.com/questions/37519828

}
output = new Response(body, response_options);
resolve$$1(output);
resolve$$1(new Response(body, response_options));
});

@@ -1524,5 +1396,3 @@ return;

// otherwise, use response as-is
output = new Response(body, response_options);
resolve$$1(output);
return;
resolve$$1(new Response(body, response_options));
});

@@ -1547,2 +1417,2 @@

export { Headers, Request, Response };export default fetch;
export { Headers, Request, Response, FetchError };export default fetch;

@@ -7,4 +7,2 @@ 'use strict';

var _getIterator = _interopDefault(require('babel-runtime/core-js/get-iterator'));
var _Object$keys = _interopDefault(require('babel-runtime/core-js/object/keys'));
var url = require('url');

@@ -14,19 +12,5 @@ var http = require('http');

var zlib = require('zlib');
var stream = require('stream');
var _Object$assign = _interopDefault(require('babel-runtime/core-js/object/assign'));
var _classCallCheck = _interopDefault(require('babel-runtime/helpers/classCallCheck'));
var _createClass = _interopDefault(require('babel-runtime/helpers/createClass'));
var _Symbol = _interopDefault(require('babel-runtime/core-js/symbol'));
var Stream = require('stream');
var Stream__default = _interopDefault(Stream);
var encoding = require('encoding');
var bodyStream = _interopDefault(require('is-stream'));
var toArrayBuffer = _interopDefault(require('buffer-to-arraybuffer'));
var _Symbol$toStringTag = _interopDefault(require('babel-runtime/core-js/symbol/to-string-tag'));
var _Object$defineProperty = _interopDefault(require('babel-runtime/core-js/object/define-property'));
var _Object$create = _interopDefault(require('babel-runtime/core-js/object/create'));
var _possibleConstructorReturn = _interopDefault(require('babel-runtime/helpers/possibleConstructorReturn'));
var _inherits = _interopDefault(require('babel-runtime/helpers/inherits'));
var _Object$getPrototypeOf = _interopDefault(require('babel-runtime/core-js/object/get-prototype-of'));
var _Object$setPrototypeOf = _interopDefault(require('babel-runtime/core-js/object/set-prototype-of'));
var _Array$from = _interopDefault(require('babel-runtime/core-js/array/from'));
var _Symbol$iterator = _interopDefault(require('babel-runtime/core-js/symbol/iterator'));

@@ -36,11 +20,9 @@ // Based on https://github.com/tmpvar/jsdom/blob/aa85b2abf07766ff7bf5c1f6daafb3726f2f2db5/lib/jsdom/living/blob.js

var BUFFER = _Symbol('buffer');
var TYPE = _Symbol('type');
var CLOSED = _Symbol('closed');
const BUFFER = Symbol('buffer');
const TYPE = Symbol('type');
const CLOSED = Symbol('closed');
var Blob = function () {
function Blob() {
_classCallCheck(this, Blob);
_Object$defineProperty(this, _Symbol$toStringTag, {
class Blob {
constructor() {
Object.defineProperty(this, Symbol.toStringTag, {
value: 'Blob',

@@ -55,13 +37,13 @@ writable: false,

var blobParts = arguments[0];
var options = arguments[1];
const blobParts = arguments[0];
const options = arguments[1];
var buffers = [];
const buffers = [];
if (blobParts) {
var a = blobParts;
var length = Number(a.length);
for (var i = 0; i < length; i++) {
var element = a[i];
var buffer = void 0;
const a = blobParts;
const length = Number(a.length);
for (let i = 0; i < length; i++) {
const element = a[i];
let buffer;
if (element instanceof Buffer) {

@@ -84,3 +66,3 @@ buffer = element;

var type = options && options.type !== undefined && String(options.type).toLowerCase();
let type = options && options.type !== undefined && String(options.type).toLowerCase();
if (type && !/[^\u0020-\u007E]/.test(type)) {

@@ -90,10 +72,17 @@ this[TYPE] = type;

}
get size() {
return this[CLOSED] ? 0 : this[BUFFER].length;
}
get type() {
return this[TYPE];
}
get isClosed() {
return this[CLOSED];
}
slice() {
const size = this.size;
Blob.prototype.slice = function slice() {
var size = this.size;
var start = arguments[0];
var end = arguments[1];
var relativeStart = void 0,
relativeEnd = void 0;
const start = arguments[0];
const end = arguments[1];
let relativeStart, relativeEnd;
if (start === undefined) {

@@ -113,37 +102,17 @@ relativeStart = 0;

}
var span = Math.max(relativeEnd - relativeStart, 0);
const span = Math.max(relativeEnd - relativeStart, 0);
var buffer = this[BUFFER];
var slicedBuffer = buffer.slice(relativeStart, relativeStart + span);
var blob = new Blob([], { type: arguments[2] });
const buffer = this[BUFFER];
const slicedBuffer = buffer.slice(relativeStart, relativeStart + span);
const blob = new Blob([], { type: arguments[2] });
blob[BUFFER] = slicedBuffer;
blob[CLOSED] = this[CLOSED];
return blob;
};
Blob.prototype.close = function close() {
}
close() {
this[CLOSED] = true;
};
}
}
_createClass(Blob, [{
key: 'size',
get: function get() {
return this[CLOSED] ? 0 : this[BUFFER].length;
}
}, {
key: 'type',
get: function get() {
return this[TYPE];
}
}, {
key: 'isClosed',
get: function get() {
return this[CLOSED];
}
}]);
return Blob;
}();
_Object$defineProperty(Blob.prototype, _Symbol$toStringTag, {
Object.defineProperty(Blob.prototype, Symbol.toStringTag, {
value: 'BlobPrototype',

@@ -184,3 +153,3 @@ writable: false,

FetchError.prototype = _Object$create(Error.prototype);
FetchError.prototype = Object.create(Error.prototype);
FetchError.prototype.constructor = FetchError;

@@ -195,4 +164,3 @@ FetchError.prototype.name = 'FetchError';

var DISTURBED = _Symbol('disturbed');
var CONSUME_BODY = _Symbol('consumeBody');
const DISTURBED = Symbol('disturbed');

@@ -202,2 +170,4 @@ /**

*
* Cannot use ES6 class because Body must be called with .call().
*
* @param Stream body Readable stream

@@ -207,35 +177,37 @@ * @param Object opts Response options

*/
function Body(body) {
var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
_ref$size = _ref.size;
var Body = function () {
function Body(body) {
var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
_ref$size = _ref.size,
size = _ref$size === undefined ? 0 : _ref$size,
_ref$timeout = _ref.timeout,
timeout = _ref$timeout === undefined ? 0 : _ref$timeout;
let size = _ref$size === undefined ? 0 : _ref$size;
var _ref$timeout = _ref.timeout;
let timeout = _ref$timeout === undefined ? 0 : _ref$timeout;
_classCallCheck(this, Body);
if (body == null) {
// body is undefined or null
body = null;
} else if (typeof body === 'string') {
// body is string
} else if (body instanceof Blob) {
// body is blob
} else if (Buffer.isBuffer(body)) {
// body is buffer
} else if (bodyStream(body)) {
// body is stream
} else {
// none of the above
// coerce to string
body = String(body);
}
this.body = body;
this[DISTURBED] = false;
this.size = size;
this.timeout = timeout;
if (body == null) {
// body is undefined or null
body = null;
} else if (typeof body === 'string') {
// body is string
} else if (body instanceof Blob) {
// body is blob
} else if (Buffer.isBuffer(body)) {
// body is buffer
} else if (body instanceof Stream__default) {
// body is stream
} else {
// none of the above
// coerce to string
body = String(body);
}
this.body = body;
this[DISTURBED] = false;
this.size = size;
this.timeout = timeout;
}
Body.prototype = {
get bodyUsed() {
return this[DISTURBED];
},
/**

@@ -246,7 +218,7 @@ * Decode response as ArrayBuffer

*/
Body.prototype.arrayBuffer = function arrayBuffer() {
return this[CONSUME_BODY]().then(function (buf) {
return toArrayBuffer(buf);
arrayBuffer() {
return consumeBody.call(this).then(function (buf) {
return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
});
};
},

@@ -258,16 +230,14 @@ /**

*/
Body.prototype.blob = function blob() {
var ct = this.headers && this.headers.get('content-type') || '';
return this[CONSUME_BODY]().then(function (buf) {
var _Object$assign2;
return _Object$assign(
blob() {
let ct = this.headers && this.headers.get('content-type') || '';
return consumeBody.call(this).then(function (buf) {
return Object.assign(
// Prevent copying
new Blob([], {
type: ct.toLowerCase()
}), (_Object$assign2 = {}, _Object$assign2[BUFFER] = buf, _Object$assign2));
}), {
[BUFFER]: buf
});
});
};
},

@@ -279,9 +249,7 @@ /**

*/
Body.prototype.json = function json() {
return this[CONSUME_BODY]().then(function (buffer) {
json() {
return consumeBody.call(this).then(function (buffer) {
return JSON.parse(buffer.toString());
});
};
},

@@ -293,9 +261,7 @@ /**

*/
Body.prototype.text = function text() {
return this[CONSUME_BODY]().then(function (buffer) {
text() {
return consumeBody.call(this).then(function (buffer) {
return buffer.toString();
});
};
},

@@ -307,8 +273,6 @@ /**

*/
buffer() {
return consumeBody.call(this);
},
Body.prototype.buffer = function buffer() {
return this[CONSUME_BODY]();
};
/**

@@ -320,116 +284,121 @@ * Decode response as text, while automatically detecting the encoding and

*/
Body.prototype.textConverted = function textConverted() {
textConverted() {
var _this = this;
return this[CONSUME_BODY]().then(function (buffer) {
return consumeBody.call(this).then(function (buffer) {
return convertBody(buffer, _this.headers);
});
};
}
/**
* Decode buffers into utf-8 string
*
* @return Promise
*/
};
Body.prototype[CONSUME_BODY] = function () {
var _this2 = this;
if (this[DISTURBED]) {
return Body.Promise.reject(new Error('body used already for: ' + this.url));
Body.mixIn = function (proto) {
for (const name of Object.getOwnPropertyNames(Body.prototype)) {
// istanbul ignore else: future proof
if (!(name in proto)) {
const desc = Object.getOwnPropertyDescriptor(Body.prototype, name);
Object.defineProperty(proto, name, desc);
}
}
};
this[DISTURBED] = true;
/**
* Decode buffers into utf-8 string
*
* @return Promise
*/
function consumeBody(body) {
var _this2 = this;
// body is null
if (this.body === null) {
return Body.Promise.resolve(new Buffer(0));
}
if (this[DISTURBED]) {
return Body.Promise.reject(new Error(`body used already for: ${this.url}`));
}
// body is string
if (typeof this.body === 'string') {
return Body.Promise.resolve(new Buffer(this.body));
}
this[DISTURBED] = true;
// body is blob
if (this.body instanceof Blob) {
return Body.Promise.resolve(this.body[BUFFER]);
}
// body is null
if (this.body === null) {
return Body.Promise.resolve(new Buffer(0));
}
// body is buffer
if (Buffer.isBuffer(this.body)) {
return Body.Promise.resolve(this.body);
}
// body is string
if (typeof this.body === 'string') {
return Body.Promise.resolve(new Buffer(this.body));
}
// istanbul ignore if: should never happen
if (!bodyStream(this.body)) {
return Body.Promise.resolve(new Buffer(0));
}
// body is blob
if (this.body instanceof Blob) {
return Body.Promise.resolve(this.body[BUFFER]);
}
// body is stream
// get ready to actually consume the body
var accum = [];
var accumBytes = 0;
var abort = false;
// body is buffer
if (Buffer.isBuffer(this.body)) {
return Body.Promise.resolve(this.body);
}
return new Body.Promise(function (resolve$$1, reject) {
var resTimeout = void 0;
// istanbul ignore if: should never happen
if (!(this.body instanceof Stream__default)) {
return Body.Promise.resolve(new Buffer(0));
}
// allow timeout on slow response body
if (_this2.timeout) {
resTimeout = setTimeout(function () {
abort = true;
reject(new FetchError('Response timeout while trying to fetch ' + _this2.url + ' (over ' + _this2.timeout + 'ms)', 'body-timeout'));
}, _this2.timeout);
}
// body is stream
// get ready to actually consume the body
let accum = [];
let accumBytes = 0;
let abort = false;
// handle stream error, such as incorrect content-encoding
_this2.body.on('error', function (err) {
reject(new FetchError('Invalid response body while trying to fetch ' + _this2.url + ': ' + err.message, 'system', err));
});
return new Body.Promise(function (resolve$$1, reject) {
let resTimeout;
_this2.body.on('data', function (chunk) {
if (abort || chunk === null) {
return;
}
// allow timeout on slow response body
if (_this2.timeout) {
resTimeout = setTimeout(function () {
abort = true;
reject(new FetchError(`Response timeout while trying to fetch ${_this2.url} (over ${_this2.timeout}ms)`, 'body-timeout'));
}, _this2.timeout);
}
if (_this2.size && accumBytes + chunk.length > _this2.size) {
abort = true;
reject(new FetchError('content size at ' + _this2.url + ' over limit: ' + _this2.size, 'max-size'));
return;
}
// handle stream error, such as incorrect content-encoding
_this2.body.on('error', function (err) {
reject(new FetchError(`Invalid response body while trying to fetch ${_this2.url}: ${err.message}`, 'system', err));
});
accumBytes += chunk.length;
accum.push(chunk);
});
_this2.body.on('data', function (chunk) {
if (abort || chunk === null) {
return;
}
_this2.body.on('end', function () {
if (abort) {
return;
}
if (_this2.size && accumBytes + chunk.length > _this2.size) {
abort = true;
reject(new FetchError(`content size at ${_this2.url} over limit: ${_this2.size}`, 'max-size'));
return;
}
clearTimeout(resTimeout);
resolve$$1(Buffer.concat(accum));
});
accumBytes += chunk.length;
accum.push(chunk);
});
};
_createClass(Body, [{
key: 'bodyUsed',
get: function get() {
return this[DISTURBED];
}
}]);
_this2.body.on('end', function () {
if (abort) {
return;
}
return Body;
}();
clearTimeout(resTimeout);
resolve$$1(Buffer.concat(accum));
});
});
}
/**
* Detect buffer encoding and convert to target encoding
* ref: http://www.w3.org/TR/2011/WD-html5-20110113/parsing.html#determining-the-character-encoding
*
* @param Buffer buffer Incoming buffer
* @param String encoding Target encoding
* @return String
*/
function convertBody(buffer, headers) {
var ct = headers.get('content-type');
var charset = 'utf-8';
var res = void 0,
str = void 0;
const ct = headers.get('content-type');
let charset = 'utf-8';
let res, str;

@@ -484,6 +453,5 @@ // header

*/
function clone$1(instance) {
var p1 = void 0,
p2 = void 0;
var body = instance.body;
function clone(instance) {
let p1, p2;
let body = instance.body;

@@ -497,6 +465,6 @@ // don't allow cloning a used body

// note: we can't clone the form-data object without having it as a dependency
if (bodyStream(body) && typeof body.getBoundary !== 'function') {
if (body instanceof Stream__default && typeof body.getBoundary !== 'function') {
// tee instance body
p1 = new stream.PassThrough();
p2 = new stream.PassThrough();
p1 = new Stream.PassThrough();
p2 = new Stream.PassThrough();
body.pipe(p1);

@@ -522,3 +490,3 @@ body.pipe(p2);

function extractContentType(instance) {
var body = instance.body;
const body = instance.body;

@@ -542,3 +510,3 @@ // istanbul ignore if: Currently, because of a guard in Request, body

// detect form data input from form-data module
return 'multipart/form-data;boundary=' + body.getBoundary();
return `multipart/form-data;boundary=${body.getBoundary()}`;
} else {

@@ -552,4 +520,5 @@ // body is stream

function getTotalBytes(instance) {
var body = instance.body;
const body = instance.body;
// istanbul ignore if: included for completion

@@ -584,3 +553,3 @@ if (body === null) {

function writeToStream(dest, instance) {
var body = instance.body;
const body = instance.body;

@@ -657,3 +626,3 @@

if (!isValidTokenChar(val.charCodeAt(0))) return false;
var len = val.length;
const len = val.length;
if (len > 1) {

@@ -711,3 +680,3 @@ if (!isValidTokenChar(val.charCodeAt(1))) return false;

if (!checkIsHttpToken(name)) {
throw new TypeError(name + ' is not a legal HTTP header name');
throw new TypeError(`${name} is not a legal HTTP header name`);
}

@@ -720,3 +689,3 @@ return name.toLowerCase();

if (checkInvalidHeaderChar(value)) {
throw new TypeError(value + ' is not a legal HTTP header value');
throw new TypeError(`${value} is not a legal HTTP header value`);
}

@@ -726,5 +695,4 @@ return value;

var MAP = _Symbol('map');
var Headers = function () {
const MAP = Symbol('map');
class Headers {
/**

@@ -736,9 +704,20 @@ * Headers class

*/
function Headers() {
var init = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : undefined;
constructor() {
let init = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : undefined;
_classCallCheck(this, Headers);
this[MAP] = Object.create(null);
this[MAP] = _Object$create(null);
if (init instanceof Headers) {
const rawHeaders = init.raw();
const headerNames = Object.keys(rawHeaders);
for (const headerName of headerNames) {
for (const value of rawHeaders[headerName]) {
this.append(headerName, value);
}
}
return;
}
// We don't worry about converting prop to ByteString here as append()

@@ -749,3 +728,3 @@ // will handle it.

} else if (typeof init === 'object') {
var method = init[_Symbol$iterator];
const method = init[Symbol.iterator];
if (method != null) {

@@ -758,59 +737,20 @@ if (typeof method !== 'function') {

// Note: per spec we have to first exhaust the lists then process them
var pairs = [];
for (var _iterator = init, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _getIterator(_iterator);;) {
var _ref;
if (_isArray) {
if (_i >= _iterator.length) break;
_ref = _iterator[_i++];
} else {
_i = _iterator.next();
if (_i.done) break;
_ref = _i.value;
}
var pair = _ref;
if (typeof pair !== 'object' || typeof pair[_Symbol$iterator] !== 'function') {
const pairs = [];
for (const pair of init) {
if (typeof pair !== 'object' || typeof pair[Symbol.iterator] !== 'function') {
throw new TypeError('Each header pair must be iterable');
}
pairs.push(_Array$from(pair));
pairs.push(Array.from(pair));
}
for (var _iterator2 = pairs, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _getIterator(_iterator2);;) {
var _ref2;
if (_isArray2) {
if (_i2 >= _iterator2.length) break;
_ref2 = _iterator2[_i2++];
} else {
_i2 = _iterator2.next();
if (_i2.done) break;
_ref2 = _i2.value;
}
var _pair = _ref2;
if (_pair.length !== 2) {
for (const pair of pairs) {
if (pair.length !== 2) {
throw new TypeError('Each header pair must be a name/value tuple');
}
this.append(_pair[0], _pair[1]);
this.append(pair[0], pair[1]);
}
} else {
// record<ByteString, ByteString>
for (var _iterator3 = _Object$keys(init), _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _getIterator(_iterator3);;) {
var _ref3;
if (_isArray3) {
if (_i3 >= _iterator3.length) break;
_ref3 = _iterator3[_i3++];
} else {
_i3 = _iterator3.next();
if (_i3.done) break;
_ref3 = _i3.value;
}
var key = _ref3;
var value = init[key];
for (const key of Object.keys(init)) {
const value = init[key];
this.append(key, value);

@@ -823,3 +763,3 @@ }

_Object$defineProperty(this, _Symbol$toStringTag, {
Object.defineProperty(this, Symbol.toStringTag, {
value: 'Headers',

@@ -838,6 +778,4 @@ writable: false,

*/
Headers.prototype.get = function get(name) {
var list = this[MAP][sanitizeName(name)];
get(name) {
const list = this[MAP][sanitizeName(name)];
if (!list) {

@@ -847,4 +785,4 @@ return null;

return list.join(',');
};
return list.join(', ');
}

@@ -858,13 +796,11 @@ /**

*/
forEach(callback) {
let thisArg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined;
Headers.prototype.forEach = function forEach(callback) {
var thisArg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined;
var pairs = getHeaderPairs(this);
var i = 0;
let pairs = getHeaderPairs(this);
let i = 0;
while (i < pairs.length) {
var _pairs$i = pairs[i],
name = _pairs$i[0],
value = _pairs$i[1];
var _pairs$i = pairs[i];
const name = _pairs$i[0],
value = _pairs$i[1];

@@ -875,3 +811,3 @@ callback.call(thisArg, value, name, this);

}
};
}

@@ -885,7 +821,5 @@ /**

*/
Headers.prototype.set = function set(name, value) {
set(name, value) {
this[MAP][sanitizeName(name)] = [sanitizeValue(value)];
};
}

@@ -899,5 +833,3 @@ /**

*/
Headers.prototype.append = function append(name, value) {
append(name, value) {
if (!this.has(name)) {

@@ -909,3 +841,3 @@ this.set(name, value);

this[MAP][sanitizeName(name)].push(sanitizeValue(value));
};
}

@@ -918,7 +850,5 @@ /**

*/
Headers.prototype.has = function has(name) {
has(name) {
return !!this[MAP][sanitizeName(name)];
};
}

@@ -931,7 +861,5 @@ /**

*/
Headers.prototype.delete = function _delete(name) {
delete(name) {
delete this[MAP][sanitizeName(name)];
};
}

@@ -943,5 +871,5 @@ /**

*/
Headers.prototype.raw = function raw() {
raw() {
return this[MAP];
};
}

@@ -953,7 +881,5 @@ /**

*/
Headers.prototype.keys = function keys() {
keys() {
return createHeadersIterator(this, 'key');
};
}

@@ -965,7 +891,5 @@ /**

*/
Headers.prototype.values = function values() {
values() {
return createHeadersIterator(this, 'value');
};
}

@@ -979,14 +903,9 @@ /**

*/
Headers.prototype[_Symbol$iterator] = function () {
[Symbol.iterator]() {
return createHeadersIterator(this, 'key+value');
};
}
}
Headers.prototype.entries = Headers.prototype[Symbol.iterator];
return Headers;
}();
Headers.prototype.entries = Headers.prototype[_Symbol$iterator];
_Object$defineProperty(Headers.prototype, _Symbol$toStringTag, {
Object.defineProperty(Headers.prototype, Symbol.toStringTag, {
value: 'HeadersPrototype',

@@ -999,3 +918,3 @@ writable: false,

function getHeaderPairs(headers, kind) {
var keys = _Object$keys(headers[MAP]).sort();
const keys = Object.keys(headers[MAP]).sort();
return keys.map(kind === 'key' ? function (k) {

@@ -1008,9 +927,9 @@ return [k];

var INTERNAL = _Symbol('internal');
const INTERNAL = Symbol('internal');
function createHeadersIterator(target, kind) {
var iterator = _Object$create(HeadersIteratorPrototype);
const iterator = Object.create(HeadersIteratorPrototype);
iterator[INTERNAL] = {
target: target,
kind: kind,
target,
kind,
index: 0

@@ -1021,16 +940,16 @@ };

var HeadersIteratorPrototype = _Object$setPrototypeOf({
next: function next() {
const HeadersIteratorPrototype = Object.setPrototypeOf({
next() {
// istanbul ignore if
if (!this || _Object$getPrototypeOf(this) !== HeadersIteratorPrototype) {
if (!this || Object.getPrototypeOf(this) !== HeadersIteratorPrototype) {
throw new TypeError('Value of `this` is not a HeadersIterator');
}
var _INTERNAL = this[INTERNAL],
target = _INTERNAL.target,
kind = _INTERNAL.kind,
index = _INTERNAL.index;
var _INTERNAL = this[INTERNAL];
const target = _INTERNAL.target,
kind = _INTERNAL.kind,
index = _INTERNAL.index;
var values = getHeaderPairs(target, kind);
var len = values.length;
const values = getHeaderPairs(target, kind);
const len = values.length;
if (index >= len) {

@@ -1043,6 +962,6 @@ return {

var pair = values[index];
const pair = values[index];
this[INTERNAL].index = index + 1;
var result = void 0;
let result;
if (kind === 'key') {

@@ -1061,12 +980,5 @@ result = pair[0];

}
}, _Object$getPrototypeOf(_Object$getPrototypeOf(_getIterator([]))));
}, Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]())));
// On Node.js v0.12 the %IteratorPrototype% object is broken
if (typeof HeadersIteratorPrototype[_Symbol$iterator] !== 'function') {
HeadersIteratorPrototype[_Symbol$iterator] = function () {
return this;
};
}
_Object$defineProperty(HeadersIteratorPrototype, _Symbol$toStringTag, {
Object.defineProperty(HeadersIteratorPrototype, Symbol.toStringTag, {
value: 'HeadersIterator',

@@ -1091,20 +1003,16 @@ writable: false,

*/
class Response {
constructor() {
let body = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
let opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var Response = function (_Body) {
_inherits(Response, _Body);
Body.call(this, body, opts);
function Response() {
var body = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
this.url = opts.url;
this.status = opts.status || 200;
this.statusText = opts.statusText || http.STATUS_CODES[this.status];
_classCallCheck(this, Response);
this.headers = new Headers(opts.headers);
var _this = _possibleConstructorReturn(this, _Body.call(this, body, opts));
_this.url = opts.url;
_this.status = opts.status || 200;
_this.statusText = opts.statusText || http.STATUS_CODES[_this.status];
_this.headers = new Headers(opts.headers);
_Object$defineProperty(_this, _Symbol$toStringTag, {
Object.defineProperty(this, Symbol.toStringTag, {
value: 'Response',

@@ -1115,3 +1023,2 @@ writable: false,

});
return _this;
}

@@ -1122,4 +1029,6 @@

*/
get ok() {
return this.status >= 200 && this.status < 300;
}
/**

@@ -1130,5 +1039,5 @@ * Clone this response

*/
Response.prototype.clone = function clone() {
clone() {
return new Response(clone$1(this), {
return new Response(clone(this), {
url: this.url,

@@ -1140,15 +1049,8 @@ status: this.status,

});
};
}
}
_createClass(Response, [{
key: 'ok',
get: function get() {
return this.status >= 200 && this.status < 300;
}
}]);
Body.mixIn(Response.prototype);
return Response;
}(Body);
_Object$defineProperty(Response.prototype, _Symbol$toStringTag, {
Object.defineProperty(Response.prototype, Symbol.toStringTag, {
value: 'ResponsePrototype',

@@ -1166,3 +1068,3 @@ writable: false,

var PARSED_URL = _Symbol('url');
const PARSED_URL = Symbol('url');

@@ -1176,13 +1078,8 @@ /**

*/
class Request {
constructor(input) {
let init = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var Request = function (_Body) {
_inherits(Request, _Body);
let parsedURL;
function Request(input) {
var init = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
_classCallCheck(this, Request);
var parsedURL = void 0;
// normalize input

@@ -1197,3 +1094,3 @@ if (!(input instanceof Request)) {

// coerce input to a string before attempting to parse
parsedURL = url.parse('' + input);
parsedURL = url.parse(`${input}`);
}

@@ -1205,3 +1102,3 @@ input = {};

var method = init.method || input.method || 'GET';
let method = init.method || input.method || 'GET';

@@ -1212,18 +1109,18 @@ if ((init.body != null || input instanceof Request && input.body !== null) && (method === 'GET' || method === 'HEAD')) {

var inputBody = init.body != null ? init.body : input instanceof Request && input.body !== null ? clone$1(input) : null;
let inputBody = init.body != null ? init.body : input instanceof Request && input.body !== null ? clone(input) : null;
// fetch spec options
var _this = _possibleConstructorReturn(this, _Body.call(this, inputBody, {
Body.call(this, inputBody, {
timeout: init.timeout || input.timeout || 0,
size: init.size || input.size || 0
}));
});
_this.method = method.toUpperCase();
_this.redirect = init.redirect || input.redirect || 'follow';
_this.headers = new Headers(init.headers || input.headers || {});
// fetch spec options
this.method = method.toUpperCase();
this.redirect = init.redirect || input.redirect || 'follow';
this.headers = new Headers(init.headers || input.headers || {});
if (init.body != null) {
var contentType = extractContentType(_this);
if (contentType !== null && !_this.headers.has('Content-Type')) {
_this.headers.append('Content-Type', contentType);
const contentType = extractContentType(this);
if (contentType !== null && !this.headers.has('Content-Type')) {
this.headers.append('Content-Type', contentType);
}

@@ -1233,9 +1130,9 @@ }

// server only options
_this.follow = init.follow !== undefined ? init.follow : input.follow !== undefined ? input.follow : 20;
_this.compress = init.compress !== undefined ? init.compress : input.compress !== undefined ? input.compress : true;
_this.counter = init.counter || input.counter || 0;
_this.agent = init.agent || input.agent;
this.follow = init.follow !== undefined ? init.follow : input.follow !== undefined ? input.follow : 20;
this.compress = init.compress !== undefined ? init.compress : input.compress !== undefined ? input.compress : true;
this.counter = init.counter || input.counter || 0;
this.agent = init.agent || input.agent;
_this[PARSED_URL] = parsedURL;
_Object$defineProperty(_this, _Symbol$toStringTag, {
this[PARSED_URL] = parsedURL;
Object.defineProperty(this, Symbol.toStringTag, {
value: 'Request',

@@ -1246,5 +1143,8 @@ writable: false,

});
return _this;
}
get url() {
return url.format(this[PARSED_URL]);
}
/**

@@ -1255,17 +1155,10 @@ * Clone this request

*/
Request.prototype.clone = function clone$1() {
clone() {
return new Request(this);
};
}
}
_createClass(Request, [{
key: 'url',
get: function get() {
return url.format(this[PARSED_URL]);
}
}]);
Body.mixIn(Request.prototype);
return Request;
}(Body);
_Object$defineProperty(Request.prototype, _Symbol$toStringTag, {
Object.defineProperty(Request.prototype, Symbol.toStringTag, {
value: 'RequestPrototype',

@@ -1278,3 +1171,4 @@ writable: false,

function getNodeRequestOptions(request) {
var headers = new Headers(request.headers);
const parsedURL = request[PARSED_URL];
const headers = new Headers(request.headers);

@@ -1287,8 +1181,12 @@ // fetch step 3

// Basic fetch
if (!/^https?:$/.test(request[PARSED_URL].protocol)) {
throw new Error('only http(s) protocols are supported');
if (!parsedURL.protocol || !parsedURL.hostname) {
throw new TypeError('Only absolute URLs are supported');
}
if (!/^https?:$/.test(parsedURL.protocol)) {
throw new TypeError('Only HTTP(S) protocols are supported');
}
// HTTP-network-or-cache fetch steps 5-9
var contentLengthValue = null;
let contentLengthValue = null;
if (request.body == null && /^(POST|PUT)$/i.test(request.method)) {

@@ -1298,3 +1196,3 @@ contentLengthValue = '0';

if (request.body != null) {
var totalBytes = getTotalBytes(request);
const totalBytes = getTotalBytes(request);
if (typeof totalBytes === 'number') {

@@ -1324,3 +1222,3 @@ contentLengthValue = String(totalBytes);

return _Object$assign({}, request[PARSED_URL], {
return Object.assign({}, parsedURL, {
method: request.method,

@@ -1357,12 +1255,7 @@ headers: headers.raw(),

// build request object
var request = new Request(url$$1, opts);
const request = new Request(url$$1, opts);
const options = getNodeRequestOptions(request);
var options = getNodeRequestOptions(request);
const send = (options.protocol === 'https:' ? https : http).request;
if (!options.protocol || !options.hostname) {
throw new Error('only absolute urls are supported');
}
var send = (options.protocol === 'https:' ? https : http).request;
// http.request only support string as host header, this hack make custom host header possible

@@ -1374,4 +1267,4 @@ if (options.headers.host) {

// send request
var req = send(options);
var reqTimeout = void 0;
const req = send(options);
let reqTimeout;

@@ -1382,3 +1275,3 @@ if (request.timeout) {

req.abort();
reject(new FetchError('network timeout at: ' + request.url, 'request-timeout'));
reject(new FetchError(`network timeout at: ${request.url}`, 'request-timeout'));
}, request.timeout);

@@ -1390,3 +1283,3 @@ });

clearTimeout(reqTimeout);
reject(new FetchError('request to ' + request.url + ' failed, reason: ' + err.message, 'system', err));
reject(new FetchError(`request to ${request.url} failed, reason: ${err.message}`, 'system', err));
});

@@ -1400,3 +1293,3 @@

if (request.redirect === 'error') {
reject(new FetchError('redirect mode is set to error: ' + request.url, 'no-redirect'));
reject(new FetchError(`redirect mode is set to error: ${request.url}`, 'no-redirect'));
return;

@@ -1406,3 +1299,3 @@ }

if (request.counter >= request.follow) {
reject(new FetchError('maximum redirect reached at: ' + request.url, 'max-redirect'));
reject(new FetchError(`maximum redirect reached at: ${request.url}`, 'max-redirect'));
return;

@@ -1412,3 +1305,3 @@ }

if (!res.headers.location) {
reject(new FetchError('redirect location header missing at: ' + request.url, 'invalid-redirect'));
reject(new FetchError(`redirect location header missing at: ${request.url}`, 'invalid-redirect'));
return;

@@ -1431,36 +1324,10 @@ }

// normalize location header for manual redirect mode
var headers = new Headers();
for (var _iterator = _Object$keys(res.headers), _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _getIterator(_iterator);;) {
var _ref;
if (_isArray) {
if (_i >= _iterator.length) break;
_ref = _iterator[_i++];
} else {
_i = _iterator.next();
if (_i.done) break;
_ref = _i.value;
}
var _name = _ref;
if (Array.isArray(res.headers[_name])) {
for (var _iterator2 = res.headers[_name], _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _getIterator(_iterator2);;) {
var _ref2;
if (_isArray2) {
if (_i2 >= _iterator2.length) break;
_ref2 = _iterator2[_i2++];
} else {
_i2 = _iterator2.next();
if (_i2.done) break;
_ref2 = _i2.value;
}
var val = _ref2;
headers.append(_name, val);
const headers = new Headers();
for (const name of Object.keys(res.headers)) {
if (Array.isArray(res.headers[name])) {
for (const val of res.headers[name]) {
headers.append(name, val);
}
} else {
headers.append(_name, res.headers[_name]);
headers.append(name, res.headers[name]);
}

@@ -1473,4 +1340,4 @@ }

// prepare response
var body = res.pipe(new stream.PassThrough());
var response_options = {
let body = res.pipe(new Stream.PassThrough());
const response_options = {
url: request.url,

@@ -1484,32 +1351,40 @@ status: res.statusCode,

// response object
var output = void 0;
// HTTP-network fetch step 16.1.2
const codings = headers.get('Content-Encoding');
// HTTP-network fetch step 16.1.3: handle content codings
// in following scenarios we ignore compression support
// 1. compression support is disabled
// 2. HEAD request
// 3. no content-encoding header
// 3. no Content-Encoding header
// 4. no content response (204)
// 5. content not modified response (304)
if (!request.compress || request.method === 'HEAD' || !headers.has('content-encoding') || res.statusCode === 204 || res.statusCode === 304) {
output = new Response(body, response_options);
resolve$$1(output);
if (!request.compress || request.method === 'HEAD' || codings === null || res.statusCode === 204 || res.statusCode === 304) {
resolve$$1(new Response(body, response_options));
return;
}
// otherwise, check for gzip or deflate
var name = headers.get('content-encoding');
// For Node v6+
// Be less strict when decoding compressed responses, since sometimes
// servers send slightly invalid responses that are still accepted
// by common browsers.
// Always using Z_SYNC_FLUSH is what cURL does.
const zlibOptions = {
flush: zlib.Z_SYNC_FLUSH,
finishFlush: zlib.Z_SYNC_FLUSH
};
// for gzip
if (name == 'gzip' || name == 'x-gzip') {
body = body.pipe(zlib.createGunzip());
output = new Response(body, response_options);
resolve$$1(output);
if (codings == 'gzip' || codings == 'x-gzip') {
body = body.pipe(zlib.createGunzip(zlibOptions));
resolve$$1(new Response(body, response_options));
return;
}
// for deflate
} else if (name == 'deflate' || name == 'x-deflate') {
// for deflate
if (codings == 'deflate' || codings == 'x-deflate') {
// handle the infamous raw deflate response from old servers
// a hack for old IIS and Apache servers
var raw = res.pipe(new stream.PassThrough());
const raw = res.pipe(new Stream.PassThrough());
raw.once('data', function (chunk) {

@@ -1522,4 +1397,3 @@ // see http://stackoverflow.com/questions/37519828

}
output = new Response(body, response_options);
resolve$$1(output);
resolve$$1(new Response(body, response_options));
});

@@ -1530,5 +1404,3 @@ return;

// otherwise, use response as-is
output = new Response(body, response_options);
resolve$$1(output);
return;
resolve$$1(new Response(body, response_options));
});

@@ -1557,1 +1429,2 @@

exports.Response = Response;
exports.FetchError = FetchError;
{
"name": "node-fetch",
"version": "2.0.0-alpha.3",
"version": "2.0.0-alpha.4",
"description": "A light-weight module that brings window.fetch to node.js",
"main": "lib/index.js",
"browser": "./browser.js",
"module": "lib/index.es.js",

@@ -11,2 +12,5 @@ "files": [

],
"engines": {
"node": ">=4"
},
"scripts": {

@@ -35,7 +39,5 @@ "build": "cross-env BABEL_ENV=rollup rollup -c",

"devDependencies": {
"babel-plugin-istanbul": "^3.0.0",
"babel-plugin-transform-runtime": "^6.15.0",
"babel-preset-env": "^1.1.8",
"babel-plugin-istanbul": "^4.0.0",
"babel-preset-env": "^1.1.10",
"babel-register": "^6.16.3",
"bluebird": "^3.3.4",
"chai": "^3.5.0",

@@ -46,3 +48,3 @@ "chai-as-promised": "^6.0.0",

"codecov": "^1.0.1",
"cross-env": "2.0.1",
"cross-env": "^3.1.4",
"form-data": ">=1.0.0",

@@ -55,13 +57,9 @@ "is-builtin-module": "^1.0.0",

"resumer": "0.0.0",
"rollup": "^0.37.0",
"rollup": "^0.41.4",
"rollup-plugin-babel": "^2.6.1",
"rollup-plugin-node-resolve": "^2.0.0",
"whatwg-url": "^4.0.0"
},
"dependencies": {
"babel-runtime": "^6.11.6",
"buffer-to-arraybuffer": "0.0.4",
"encoding": "^0.1.11",
"is-stream": "^1.0.1"
"encoding": "^0.1.11"
}
}

@@ -12,5 +12,5 @@

# Motivation
## Motivation
Instead of implementing `XMLHttpRequest` in Node.js to run browser-specific [Fetch polyfill](https://github.com/github/fetch), why not go from native `http` to `Fetch` API directly? Hence `node-fetch`, minimal code for a `window.fetch` compatible API on Node.js runtime.
Instead of implementing `XMLHttpRequest` in Node.js to run browser-specific [Fetch polyfill](https://github.com/github/fetch), why not go from native `http` to `fetch` API directly? Hence `node-fetch`, minimal code for a `window.fetch` compatible API on Node.js runtime.

@@ -20,13 +20,13 @@ See Matt Andrews' [isomorphic-fetch](https://github.com/matthew-andrews/isomorphic-fetch) for isomorphic usage (exports `node-fetch` for server-side, `whatwg-fetch` for client-side).

# Features
## Features
- Stay consistent with `window.fetch` API.
- Make conscious trade-off when following [whatwg fetch spec](https://fetch.spec.whatwg.org/) and [stream spec](https://streams.spec.whatwg.org/) implementation details, document known difference.
- Make conscious trade-off when following [whatwg fetch spec][whatwg-fetch] and [stream spec](https://streams.spec.whatwg.org/) implementation details, document known difference.
- Use native promise, but allow substituting it with [insert your favorite promise library].
- Use native stream for body, on both request and response.
- Decode content encoding (gzip/deflate) properly, and convert string output (such as `res.text()` and `res.json()`) to UTF-8 automatically.
- Useful extensions such as timeout, redirect limit, response size limit, [explicit errors](https://github.com/bitinn/node-fetch/blob/master/ERROR-HANDLING.md) for troubleshooting.
- Useful extensions such as timeout, redirect limit, response size limit, [explicit errors][] for troubleshooting.
# Difference from client-side fetch
## Difference from client-side fetch

@@ -38,8 +38,10 @@ - See [Known Differences](https://github.com/bitinn/node-fetch/blob/master/LIMITS.md) for details.

# Install
## Install
`npm install node-fetch --save`
```sh
$ npm install node-fetch --save
```
# Usage
## Usage

@@ -165,37 +167,215 @@ ```javascript

# API
## API
## fetch(url, options)
### fetch(url[, options])
Returns a `Promise`
- `url` A string representing the URL for fetching
- `options` [Options](#fetch-options) for the HTTP(S) request
- Returns: <code>Promise&lt;[Response](#class-response)&gt;</code>
### Url
Perform an HTTP(S) fetch.
Should be an absolute url, eg `http://example.com/`
`url` should be an absolute url, such as `http://example.com/`. A path-relative URL (`/file/under/root`) or protocol-relative URL (`//can-be-http-or-https.com/`) will result in a rejected promise.
### Options
<a id="fetch-options"></a>
#### Options
Note that only `method`, `headers`, `redirect` and `body` are allowed in `window.fetch`. Other options are node.js extensions. The default values are shown after each option key.
The default values are shown after each option key.
```
```js
{
method: 'GET'
, headers: {} // request header. format {a:'1'} or {b:['1','2','3']}
, redirect: 'follow' // set to `manual` to extract redirect headers, `error` to reject redirect
, follow: 20 // maximum redirect count. 0 to not follow redirect
, timeout: 0 // req/res timeout in ms, it resets on redirect. 0 to disable (OS limit applies)
, compress: true // support gzip/deflate content encoding. false to disable
, size: 0 // maximum response body size in bytes. 0 to disable
, body: empty // request body. can be a string, buffer, readable stream
, agent: null // http.Agent instance, allows custom proxy, certificate etc.
// These properties are part of the Fetch Standard
method: 'GET',
headers: {}, // request headers. format is the identical to that accepted by the Headers constructor (see below)
body: null, // request body. can be null, a string, a Buffer, a Blob, or a Node.js Readable stream
redirect: 'follow', // set to `manual` to extract redirect headers, `error` to reject redirect
// The following properties are node-fetch extensions
follow: 20, // maximum redirect count. 0 to not follow redirect
timeout: 0, // req/res timeout in ms, it resets on redirect. 0 to disable (OS limit applies)
compress: true, // support gzip/deflate content encoding. false to disable
size: 0, // maximum response body size in bytes. 0 to disable
agent: null // http(s).Agent instance, allows custom proxy, certificate etc.
}
```
##### Default Headers
# License
If no values are set, the following request headers will be sent automatically:
Header | Value
----------------- | --------------------------------------------------------
`Accept-Encoding` | `gzip,deflate` _(when `options.compress === true`)_
`Accept` | `*/*`
`Connection` | `close` _(when no `options.agent` is present)_
`Content-Length` | _(automatically calculated, if possible)_
`User-Agent` | `node-fetch/1.0 (+https://github.com/bitinn/node-fetch)`
<a id="class-request"></a>
### Class: Request
An HTTP(S) request containing information about URL, method, headers, and the body. This class implements the [Body](#iface-body) interface.
Due to the nature of Node.js, the following properties are not implemented at this moment:
- `type`
- `destination`
- `referrer`
- `referrerPolicy`
- `mode`
- `credentials`
- `cache`
- `integrity`
- `keepalive`
The following node-fetch extension properties are provided:
- `follow`
- `compress`
- `counter`
- `agent`
See [options](#fetch-options) for exact meaning of these extensions.
#### new Request(input[, options])
<small>*(spec-compliant)*</small>
- `input` A string representing a URL, or another `Request` (which will be cloned)
- `options` [Options][#fetch-options] for the HTTP(S) request
Constructs a new `Request` object. The constructor is identical to that in the [browser](https://developer.mozilla.org/en-US/docs/Web/API/Request/Request).
In most cases, directly `fetch(url, options)` is simpler than creating a `Request` object.
<a id="class-response"></a>
### Class: Response
An HTTP(S) response. This class implements the [Body](#iface-body) interface.
The following properties are not implemented in node-fetch at this moment:
- `Response.error()`
- `Response.redirect()`
- `type`
- `redirected`
- `trailer`
#### new Response([body[, options]])
<small>*(spec-compliant)*</small>
- `body` A string or [Readable stream][node-readable]
- `options` A [`ResponseInit`][response-init] options dictionary
Constructs a new `Response` object. The constructor is identical to that in the [browser](https://developer.mozilla.org/en-US/docs/Web/API/Response/Response).
Because Node.js does not implement service workers (for which this class was designed), one rarely has to construct a `Response` directly.
#### response.ok
Convenience property representing if the request ended normally. Will evaluate to true if the response status was greater than or equal to 200 but smaller than 300.
<a id="class-headers"></a>
### Class: Headers
This class allows manipulating and iterating over a set of HTTP headers. All methods specified in the [Fetch Standard][whatwg-fetch] are implemented.
#### new Headers([init])
<small>*(spec-compliant)*</small>
- `init` Optional argument to pre-fill the `Headers` object
Construct a new `Headers` object. `init` can be either `null`, a `Headers` object, an key-value map object, or any iterable object.
```js
// Example adapted from https://fetch.spec.whatwg.org/#example-headers-class
const meta = {
'Content-Type': 'text/xml',
'Breaking-Bad': '<3'
};
const headers = new Headers(meta);
// The above is equivalent to
const meta = [
[ 'Content-Type', 'text/xml' ],
[ 'Breaking-Bad', '<3' ]
];
const headers = new Headers(meta);
// You can in fact use any iterable objects, like a Map or even another Headers
const meta = new Map();
meta.set('Content-Type', 'text/xml');
meta.set('Breaking-Bad', '<3');
const headers = new Headers(meta);
const copyOfHeaders = new Headers(headers);
```
<a id="iface-body"></a>
### Interface: Body
`Body` is an abstract interface with methods that are applicable to both `Request` and `Response` classes.
The following methods are not yet implemented in node-fetch at this moment:
- `formData()`
#### body.body
<small>*(deviation from spec)*</small>
* Node.js [`Readable` stream][node-readable]
The data encapsulated in the `Body` object. Note that while the [Fetch Standard][whatwg-fetch] requires the property to always be a WHATWG `ReadableStream`, in node-fetch it is a Node.js [`Readable` stream][node-readable].
#### body.bodyUsed
<small>*(spec-compliant)*</small>
* `Boolean`
A boolean property for if this body has been consumed. Per spec, a consumed body cannot be used again.
#### body.arrayBuffer()
#### body.blob()
#### body.json()
#### body.text()
<small>*(spec-compliant)*</small>
* Returns: <code>Promise</code>
Consume the body and return a promise that will resolve to one of these formats.
#### body.buffer()
<small>*(node-fetch extension)*</small>
* Returns: <code>Promise&lt;Buffer&gt;</code>
Consume the body and return a promise that will resolve to a Buffer.
#### body.textConverted()
<small>*(node-fetch extension)*</small>
* Returns: <code>Promise&lt;String&gt;</code>
Identical to `body.text()`, except instead of always converting to UTF-8, encoding sniffing will be performed and text converted to UTF-8, if possible.
<a id="class-fetcherror"></a>
### Class: FetchError
<small>*(node-fetch extension)*</small>
An operational error in the fetching process. See [ERROR-HANDLING.md][] for more info.
## License
MIT
# Acknowledgement
## Acknowledgement

@@ -211,1 +391,6 @@ Thanks to [github/fetch](https://github.com/github/fetch) for providing a solid implementation reference.

[codecov-url]: https://codecov.io/gh/bitinn/node-fetch
[ERROR-HANDLING.md]: https://github.com/bitinn/node-fetch/blob/master/ERROR-HANDLING.md
[whatwg-fetch]: https://fetch.spec.whatwg.org/
[response-init]: https://fetch.spec.whatwg.org/#responseinit
[node-readable]: https://nodejs.org/api/stream.html#stream_readable_streams
[mdn-headers]: https://developer.mozilla.org/en-US/docs/Web/API/Headers
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc