Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-go / node_modules / node-fetch / lib / index.es.js
1 process.emitWarning("The .es.js file is deprecated. Use .mjs instead.");
2
3 import Stream from 'stream';
4 import http from 'http';
5 import Url from 'url';
6 import https from 'https';
7 import zlib from 'zlib';
8
9 // Based on https://github.com/tmpvar/jsdom/blob/aa85b2abf07766ff7bf5c1f6daafb3726f2f2db5/lib/jsdom/living/blob.js
10
11 // fix for "Readable" isn't a named export issue
12 const Readable = Stream.Readable;
13
14 const BUFFER = Symbol('buffer');
15 const TYPE = Symbol('type');
16
17 class Blob {
18         constructor() {
19                 this[TYPE] = '';
20
21                 const blobParts = arguments[0];
22                 const options = arguments[1];
23
24                 const buffers = [];
25                 let size = 0;
26
27                 if (blobParts) {
28                         const a = blobParts;
29                         const length = Number(a.length);
30                         for (let i = 0; i < length; i++) {
31                                 const element = a[i];
32                                 let buffer;
33                                 if (element instanceof Buffer) {
34                                         buffer = element;
35                                 } else if (ArrayBuffer.isView(element)) {
36                                         buffer = Buffer.from(element.buffer, element.byteOffset, element.byteLength);
37                                 } else if (element instanceof ArrayBuffer) {
38                                         buffer = Buffer.from(element);
39                                 } else if (element instanceof Blob) {
40                                         buffer = element[BUFFER];
41                                 } else {
42                                         buffer = Buffer.from(typeof element === 'string' ? element : String(element));
43                                 }
44                                 size += buffer.length;
45                                 buffers.push(buffer);
46                         }
47                 }
48
49                 this[BUFFER] = Buffer.concat(buffers);
50
51                 let type = options && options.type !== undefined && String(options.type).toLowerCase();
52                 if (type && !/[^\u0020-\u007E]/.test(type)) {
53                         this[TYPE] = type;
54                 }
55         }
56         get size() {
57                 return this[BUFFER].length;
58         }
59         get type() {
60                 return this[TYPE];
61         }
62         text() {
63                 return Promise.resolve(this[BUFFER].toString());
64         }
65         arrayBuffer() {
66                 const buf = this[BUFFER];
67                 const ab = buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
68                 return Promise.resolve(ab);
69         }
70         stream() {
71                 const readable = new Readable();
72                 readable._read = function () {};
73                 readable.push(this[BUFFER]);
74                 readable.push(null);
75                 return readable;
76         }
77         toString() {
78                 return '[object Blob]';
79         }
80         slice() {
81                 const size = this.size;
82
83                 const start = arguments[0];
84                 const end = arguments[1];
85                 let relativeStart, relativeEnd;
86                 if (start === undefined) {
87                         relativeStart = 0;
88                 } else if (start < 0) {
89                         relativeStart = Math.max(size + start, 0);
90                 } else {
91                         relativeStart = Math.min(start, size);
92                 }
93                 if (end === undefined) {
94                         relativeEnd = size;
95                 } else if (end < 0) {
96                         relativeEnd = Math.max(size + end, 0);
97                 } else {
98                         relativeEnd = Math.min(end, size);
99                 }
100                 const span = Math.max(relativeEnd - relativeStart, 0);
101
102                 const buffer = this[BUFFER];
103                 const slicedBuffer = buffer.slice(relativeStart, relativeStart + span);
104                 const blob = new Blob([], { type: arguments[2] });
105                 blob[BUFFER] = slicedBuffer;
106                 return blob;
107         }
108 }
109
110 Object.defineProperties(Blob.prototype, {
111         size: { enumerable: true },
112         type: { enumerable: true },
113         slice: { enumerable: true }
114 });
115
116 Object.defineProperty(Blob.prototype, Symbol.toStringTag, {
117         value: 'Blob',
118         writable: false,
119         enumerable: false,
120         configurable: true
121 });
122
123 /**
124  * fetch-error.js
125  *
126  * FetchError interface for operational errors
127  */
128
129 /**
130  * Create FetchError instance
131  *
132  * @param   String      message      Error message for human
133  * @param   String      type         Error type for machine
134  * @param   String      systemError  For Node.js system error
135  * @return  FetchError
136  */
137 function FetchError(message, type, systemError) {
138   Error.call(this, message);
139
140   this.message = message;
141   this.type = type;
142
143   // when err.type is `system`, err.code contains system error code
144   if (systemError) {
145     this.code = this.errno = systemError.code;
146   }
147
148   // hide custom error implementation details from end-users
149   Error.captureStackTrace(this, this.constructor);
150 }
151
152 FetchError.prototype = Object.create(Error.prototype);
153 FetchError.prototype.constructor = FetchError;
154 FetchError.prototype.name = 'FetchError';
155
156 let convert;
157 try {
158         convert = require('encoding').convert;
159 } catch (e) {}
160
161 const INTERNALS = Symbol('Body internals');
162
163 // fix an issue where "PassThrough" isn't a named export for node <10
164 const PassThrough = Stream.PassThrough;
165
166 /**
167  * Body mixin
168  *
169  * Ref: https://fetch.spec.whatwg.org/#body
170  *
171  * @param   Stream  body  Readable stream
172  * @param   Object  opts  Response options
173  * @return  Void
174  */
175 function Body(body) {
176         var _this = this;
177
178         var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
179             _ref$size = _ref.size;
180
181         let size = _ref$size === undefined ? 0 : _ref$size;
182         var _ref$timeout = _ref.timeout;
183         let timeout = _ref$timeout === undefined ? 0 : _ref$timeout;
184
185         if (body == null) {
186                 // body is undefined or null
187                 body = null;
188         } else if (isURLSearchParams(body)) {
189                 // body is a URLSearchParams
190                 body = Buffer.from(body.toString());
191         } else if (isBlob(body)) ; else if (Buffer.isBuffer(body)) ; else if (Object.prototype.toString.call(body) === '[object ArrayBuffer]') {
192                 // body is ArrayBuffer
193                 body = Buffer.from(body);
194         } else if (ArrayBuffer.isView(body)) {
195                 // body is ArrayBufferView
196                 body = Buffer.from(body.buffer, body.byteOffset, body.byteLength);
197         } else if (body instanceof Stream) ; else {
198                 // none of the above
199                 // coerce to string then buffer
200                 body = Buffer.from(String(body));
201         }
202         this[INTERNALS] = {
203                 body,
204                 disturbed: false,
205                 error: null
206         };
207         this.size = size;
208         this.timeout = timeout;
209
210         if (body instanceof Stream) {
211                 body.on('error', function (err) {
212                         const error = err.name === 'AbortError' ? err : new FetchError(`Invalid response body while trying to fetch ${_this.url}: ${err.message}`, 'system', err);
213                         _this[INTERNALS].error = error;
214                 });
215         }
216 }
217
218 Body.prototype = {
219         get body() {
220                 return this[INTERNALS].body;
221         },
222
223         get bodyUsed() {
224                 return this[INTERNALS].disturbed;
225         },
226
227         /**
228   * Decode response as ArrayBuffer
229   *
230   * @return  Promise
231   */
232         arrayBuffer() {
233                 return consumeBody.call(this).then(function (buf) {
234                         return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
235                 });
236         },
237
238         /**
239   * Return raw response as Blob
240   *
241   * @return Promise
242   */
243         blob() {
244                 let ct = this.headers && this.headers.get('content-type') || '';
245                 return consumeBody.call(this).then(function (buf) {
246                         return Object.assign(
247                         // Prevent copying
248                         new Blob([], {
249                                 type: ct.toLowerCase()
250                         }), {
251                                 [BUFFER]: buf
252                         });
253                 });
254         },
255
256         /**
257   * Decode response as json
258   *
259   * @return  Promise
260   */
261         json() {
262                 var _this2 = this;
263
264                 return consumeBody.call(this).then(function (buffer) {
265                         try {
266                                 return JSON.parse(buffer.toString());
267                         } catch (err) {
268                                 return Body.Promise.reject(new FetchError(`invalid json response body at ${_this2.url} reason: ${err.message}`, 'invalid-json'));
269                         }
270                 });
271         },
272
273         /**
274   * Decode response as text
275   *
276   * @return  Promise
277   */
278         text() {
279                 return consumeBody.call(this).then(function (buffer) {
280                         return buffer.toString();
281                 });
282         },
283
284         /**
285   * Decode response as buffer (non-spec api)
286   *
287   * @return  Promise
288   */
289         buffer() {
290                 return consumeBody.call(this);
291         },
292
293         /**
294   * Decode response as text, while automatically detecting the encoding and
295   * trying to decode to UTF-8 (non-spec api)
296   *
297   * @return  Promise
298   */
299         textConverted() {
300                 var _this3 = this;
301
302                 return consumeBody.call(this).then(function (buffer) {
303                         return convertBody(buffer, _this3.headers);
304                 });
305         }
306 };
307
308 // In browsers, all properties are enumerable.
309 Object.defineProperties(Body.prototype, {
310         body: { enumerable: true },
311         bodyUsed: { enumerable: true },
312         arrayBuffer: { enumerable: true },
313         blob: { enumerable: true },
314         json: { enumerable: true },
315         text: { enumerable: true }
316 });
317
318 Body.mixIn = function (proto) {
319         for (const name of Object.getOwnPropertyNames(Body.prototype)) {
320                 // istanbul ignore else: future proof
321                 if (!(name in proto)) {
322                         const desc = Object.getOwnPropertyDescriptor(Body.prototype, name);
323                         Object.defineProperty(proto, name, desc);
324                 }
325         }
326 };
327
328 /**
329  * Consume and convert an entire Body to a Buffer.
330  *
331  * Ref: https://fetch.spec.whatwg.org/#concept-body-consume-body
332  *
333  * @return  Promise
334  */
335 function consumeBody() {
336         var _this4 = this;
337
338         if (this[INTERNALS].disturbed) {
339                 return Body.Promise.reject(new TypeError(`body used already for: ${this.url}`));
340         }
341
342         this[INTERNALS].disturbed = true;
343
344         if (this[INTERNALS].error) {
345                 return Body.Promise.reject(this[INTERNALS].error);
346         }
347
348         let body = this.body;
349
350         // body is null
351         if (body === null) {
352                 return Body.Promise.resolve(Buffer.alloc(0));
353         }
354
355         // body is blob
356         if (isBlob(body)) {
357                 body = body.stream();
358         }
359
360         // body is buffer
361         if (Buffer.isBuffer(body)) {
362                 return Body.Promise.resolve(body);
363         }
364
365         // istanbul ignore if: should never happen
366         if (!(body instanceof Stream)) {
367                 return Body.Promise.resolve(Buffer.alloc(0));
368         }
369
370         // body is stream
371         // get ready to actually consume the body
372         let accum = [];
373         let accumBytes = 0;
374         let abort = false;
375
376         return new Body.Promise(function (resolve, reject) {
377                 let resTimeout;
378
379                 // allow timeout on slow response body
380                 if (_this4.timeout) {
381                         resTimeout = setTimeout(function () {
382                                 abort = true;
383                                 reject(new FetchError(`Response timeout while trying to fetch ${_this4.url} (over ${_this4.timeout}ms)`, 'body-timeout'));
384                         }, _this4.timeout);
385                 }
386
387                 // handle stream errors
388                 body.on('error', function (err) {
389                         if (err.name === 'AbortError') {
390                                 // if the request was aborted, reject with this Error
391                                 abort = true;
392                                 reject(err);
393                         } else {
394                                 // other errors, such as incorrect content-encoding
395                                 reject(new FetchError(`Invalid response body while trying to fetch ${_this4.url}: ${err.message}`, 'system', err));
396                         }
397                 });
398
399                 body.on('data', function (chunk) {
400                         if (abort || chunk === null) {
401                                 return;
402                         }
403
404                         if (_this4.size && accumBytes + chunk.length > _this4.size) {
405                                 abort = true;
406                                 reject(new FetchError(`content size at ${_this4.url} over limit: ${_this4.size}`, 'max-size'));
407                                 return;
408                         }
409
410                         accumBytes += chunk.length;
411                         accum.push(chunk);
412                 });
413
414                 body.on('end', function () {
415                         if (abort) {
416                                 return;
417                         }
418
419                         clearTimeout(resTimeout);
420
421                         try {
422                                 resolve(Buffer.concat(accum, accumBytes));
423                         } catch (err) {
424                                 // handle streams that have accumulated too much data (issue #414)
425                                 reject(new FetchError(`Could not create Buffer from response body for ${_this4.url}: ${err.message}`, 'system', err));
426                         }
427                 });
428         });
429 }
430
431 /**
432  * Detect buffer encoding and convert to target encoding
433  * ref: http://www.w3.org/TR/2011/WD-html5-20110113/parsing.html#determining-the-character-encoding
434  *
435  * @param   Buffer  buffer    Incoming buffer
436  * @param   String  encoding  Target encoding
437  * @return  String
438  */
439 function convertBody(buffer, headers) {
440         if (typeof convert !== 'function') {
441                 throw new Error('The package `encoding` must be installed to use the textConverted() function');
442         }
443
444         const ct = headers.get('content-type');
445         let charset = 'utf-8';
446         let res, str;
447
448         // header
449         if (ct) {
450                 res = /charset=([^;]*)/i.exec(ct);
451         }
452
453         // no charset in content type, peek at response body for at most 1024 bytes
454         str = buffer.slice(0, 1024).toString();
455
456         // html5
457         if (!res && str) {
458                 res = /<meta.+?charset=(['"])(.+?)\1/i.exec(str);
459         }
460
461         // html4
462         if (!res && str) {
463                 res = /<meta[\s]+?http-equiv=(['"])content-type\1[\s]+?content=(['"])(.+?)\2/i.exec(str);
464                 if (!res) {
465                         res = /<meta[\s]+?content=(['"])(.+?)\1[\s]+?http-equiv=(['"])content-type\3/i.exec(str);
466                         if (res) {
467                                 res.pop(); // drop last quote
468                         }
469                 }
470
471                 if (res) {
472                         res = /charset=(.*)/i.exec(res.pop());
473                 }
474         }
475
476         // xml
477         if (!res && str) {
478                 res = /<\?xml.+?encoding=(['"])(.+?)\1/i.exec(str);
479         }
480
481         // found charset
482         if (res) {
483                 charset = res.pop();
484
485                 // prevent decode issues when sites use incorrect encoding
486                 // ref: https://hsivonen.fi/encoding-menu/
487                 if (charset === 'gb2312' || charset === 'gbk') {
488                         charset = 'gb18030';
489                 }
490         }
491
492         // turn raw buffers into a single utf-8 buffer
493         return convert(buffer, 'UTF-8', charset).toString();
494 }
495
496 /**
497  * Detect a URLSearchParams object
498  * ref: https://github.com/bitinn/node-fetch/issues/296#issuecomment-307598143
499  *
500  * @param   Object  obj     Object to detect by type or brand
501  * @return  String
502  */
503 function isURLSearchParams(obj) {
504         // Duck-typing as a necessary condition.
505         if (typeof obj !== 'object' || typeof obj.append !== 'function' || typeof obj.delete !== 'function' || typeof obj.get !== 'function' || typeof obj.getAll !== 'function' || typeof obj.has !== 'function' || typeof obj.set !== 'function') {
506                 return false;
507         }
508
509         // Brand-checking and more duck-typing as optional condition.
510         return obj.constructor.name === 'URLSearchParams' || Object.prototype.toString.call(obj) === '[object URLSearchParams]' || typeof obj.sort === 'function';
511 }
512
513 /**
514  * Check if `obj` is a W3C `Blob` object (which `File` inherits from)
515  * @param  {*} obj
516  * @return {boolean}
517  */
518 function isBlob(obj) {
519         return typeof obj === 'object' && typeof obj.arrayBuffer === 'function' && typeof obj.type === 'string' && typeof obj.stream === 'function' && typeof obj.constructor === 'function' && typeof obj.constructor.name === 'string' && /^(Blob|File)$/.test(obj.constructor.name) && /^(Blob|File)$/.test(obj[Symbol.toStringTag]);
520 }
521
522 /**
523  * Clone body given Res/Req instance
524  *
525  * @param   Mixed  instance  Response or Request instance
526  * @return  Mixed
527  */
528 function clone(instance) {
529         let p1, p2;
530         let body = instance.body;
531
532         // don't allow cloning a used body
533         if (instance.bodyUsed) {
534                 throw new Error('cannot clone body after it is used');
535         }
536
537         // check that body is a stream and not form-data object
538         // note: we can't clone the form-data object without having it as a dependency
539         if (body instanceof Stream && typeof body.getBoundary !== 'function') {
540                 // tee instance body
541                 p1 = new PassThrough();
542                 p2 = new PassThrough();
543                 body.pipe(p1);
544                 body.pipe(p2);
545                 // set instance body to teed body and return the other teed body
546                 instance[INTERNALS].body = p1;
547                 body = p2;
548         }
549
550         return body;
551 }
552
553 /**
554  * Performs the operation "extract a `Content-Type` value from |object|" as
555  * specified in the specification:
556  * https://fetch.spec.whatwg.org/#concept-bodyinit-extract
557  *
558  * This function assumes that instance.body is present.
559  *
560  * @param   Mixed  instance  Any options.body input
561  */
562 function extractContentType(body) {
563         if (body === null) {
564                 // body is null
565                 return null;
566         } else if (typeof body === 'string') {
567                 // body is string
568                 return 'text/plain;charset=UTF-8';
569         } else if (isURLSearchParams(body)) {
570                 // body is a URLSearchParams
571                 return 'application/x-www-form-urlencoded;charset=UTF-8';
572         } else if (isBlob(body)) {
573                 // body is blob
574                 return body.type || null;
575         } else if (Buffer.isBuffer(body)) {
576                 // body is buffer
577                 return null;
578         } else if (Object.prototype.toString.call(body) === '[object ArrayBuffer]') {
579                 // body is ArrayBuffer
580                 return null;
581         } else if (ArrayBuffer.isView(body)) {
582                 // body is ArrayBufferView
583                 return null;
584         } else if (typeof body.getBoundary === 'function') {
585                 // detect form data input from form-data module
586                 return `multipart/form-data;boundary=${body.getBoundary()}`;
587         } else if (body instanceof Stream) {
588                 // body is stream
589                 // can't really do much about this
590                 return null;
591         } else {
592                 // Body constructor defaults other things to string
593                 return 'text/plain;charset=UTF-8';
594         }
595 }
596
597 /**
598  * The Fetch Standard treats this as if "total bytes" is a property on the body.
599  * For us, we have to explicitly get it with a function.
600  *
601  * ref: https://fetch.spec.whatwg.org/#concept-body-total-bytes
602  *
603  * @param   Body    instance   Instance of Body
604  * @return  Number?            Number of bytes, or null if not possible
605  */
606 function getTotalBytes(instance) {
607         const body = instance.body;
608
609
610         if (body === null) {
611                 // body is null
612                 return 0;
613         } else if (isBlob(body)) {
614                 return body.size;
615         } else if (Buffer.isBuffer(body)) {
616                 // body is buffer
617                 return body.length;
618         } else if (body && typeof body.getLengthSync === 'function') {
619                 // detect form data input from form-data module
620                 if (body._lengthRetrievers && body._lengthRetrievers.length == 0 || // 1.x
621                 body.hasKnownLength && body.hasKnownLength()) {
622                         // 2.x
623                         return body.getLengthSync();
624                 }
625                 return null;
626         } else {
627                 // body is stream
628                 return null;
629         }
630 }
631
632 /**
633  * Write a Body to a Node.js WritableStream (e.g. http.Request) object.
634  *
635  * @param   Body    instance   Instance of Body
636  * @return  Void
637  */
638 function writeToStream(dest, instance) {
639         const body = instance.body;
640
641
642         if (body === null) {
643                 // body is null
644                 dest.end();
645         } else if (isBlob(body)) {
646                 body.stream().pipe(dest);
647         } else if (Buffer.isBuffer(body)) {
648                 // body is buffer
649                 dest.write(body);
650                 dest.end();
651         } else {
652                 // body is stream
653                 body.pipe(dest);
654         }
655 }
656
657 // expose Promise
658 Body.Promise = global.Promise;
659
660 /**
661  * headers.js
662  *
663  * Headers class offers convenient helpers
664  */
665
666 const invalidTokenRegex = /[^\^_`a-zA-Z\-0-9!#$%&'*+.|~]/;
667 const invalidHeaderCharRegex = /[^\t\x20-\x7e\x80-\xff]/;
668
669 function validateName(name) {
670         name = `${name}`;
671         if (invalidTokenRegex.test(name) || name === '') {
672                 throw new TypeError(`${name} is not a legal HTTP header name`);
673         }
674 }
675
676 function validateValue(value) {
677         value = `${value}`;
678         if (invalidHeaderCharRegex.test(value)) {
679                 throw new TypeError(`${value} is not a legal HTTP header value`);
680         }
681 }
682
683 /**
684  * Find the key in the map object given a header name.
685  *
686  * Returns undefined if not found.
687  *
688  * @param   String  name  Header name
689  * @return  String|Undefined
690  */
691 function find(map, name) {
692         name = name.toLowerCase();
693         for (const key in map) {
694                 if (key.toLowerCase() === name) {
695                         return key;
696                 }
697         }
698         return undefined;
699 }
700
701 const MAP = Symbol('map');
702 class Headers {
703         /**
704   * Headers class
705   *
706   * @param   Object  headers  Response headers
707   * @return  Void
708   */
709         constructor() {
710                 let init = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : undefined;
711
712                 this[MAP] = Object.create(null);
713
714                 if (init instanceof Headers) {
715                         const rawHeaders = init.raw();
716                         const headerNames = Object.keys(rawHeaders);
717
718                         for (const headerName of headerNames) {
719                                 for (const value of rawHeaders[headerName]) {
720                                         this.append(headerName, value);
721                                 }
722                         }
723
724                         return;
725                 }
726
727                 // We don't worry about converting prop to ByteString here as append()
728                 // will handle it.
729                 if (init == null) ; else if (typeof init === 'object') {
730                         const method = init[Symbol.iterator];
731                         if (method != null) {
732                                 if (typeof method !== 'function') {
733                                         throw new TypeError('Header pairs must be iterable');
734                                 }
735
736                                 // sequence<sequence<ByteString>>
737                                 // Note: per spec we have to first exhaust the lists then process them
738                                 const pairs = [];
739                                 for (const pair of init) {
740                                         if (typeof pair !== 'object' || typeof pair[Symbol.iterator] !== 'function') {
741                                                 throw new TypeError('Each header pair must be iterable');
742                                         }
743                                         pairs.push(Array.from(pair));
744                                 }
745
746                                 for (const pair of pairs) {
747                                         if (pair.length !== 2) {
748                                                 throw new TypeError('Each header pair must be a name/value tuple');
749                                         }
750                                         this.append(pair[0], pair[1]);
751                                 }
752                         } else {
753                                 // record<ByteString, ByteString>
754                                 for (const key of Object.keys(init)) {
755                                         const value = init[key];
756                                         this.append(key, value);
757                                 }
758                         }
759                 } else {
760                         throw new TypeError('Provided initializer must be an object');
761                 }
762         }
763
764         /**
765   * Return combined header value given name
766   *
767   * @param   String  name  Header name
768   * @return  Mixed
769   */
770         get(name) {
771                 name = `${name}`;
772                 validateName(name);
773                 const key = find(this[MAP], name);
774                 if (key === undefined) {
775                         return null;
776                 }
777
778                 return this[MAP][key].join(', ');
779         }
780
781         /**
782   * Iterate over all headers
783   *
784   * @param   Function  callback  Executed for each item with parameters (value, name, thisArg)
785   * @param   Boolean   thisArg   `this` context for callback function
786   * @return  Void
787   */
788         forEach(callback) {
789                 let thisArg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined;
790
791                 let pairs = getHeaders(this);
792                 let i = 0;
793                 while (i < pairs.length) {
794                         var _pairs$i = pairs[i];
795                         const name = _pairs$i[0],
796                               value = _pairs$i[1];
797
798                         callback.call(thisArg, value, name, this);
799                         pairs = getHeaders(this);
800                         i++;
801                 }
802         }
803
804         /**
805   * Overwrite header values given name
806   *
807   * @param   String  name   Header name
808   * @param   String  value  Header value
809   * @return  Void
810   */
811         set(name, value) {
812                 name = `${name}`;
813                 value = `${value}`;
814                 validateName(name);
815                 validateValue(value);
816                 const key = find(this[MAP], name);
817                 this[MAP][key !== undefined ? key : name] = [value];
818         }
819
820         /**
821   * Append a value onto existing header
822   *
823   * @param   String  name   Header name
824   * @param   String  value  Header value
825   * @return  Void
826   */
827         append(name, value) {
828                 name = `${name}`;
829                 value = `${value}`;
830                 validateName(name);
831                 validateValue(value);
832                 const key = find(this[MAP], name);
833                 if (key !== undefined) {
834                         this[MAP][key].push(value);
835                 } else {
836                         this[MAP][name] = [value];
837                 }
838         }
839
840         /**
841   * Check for header name existence
842   *
843   * @param   String   name  Header name
844   * @return  Boolean
845   */
846         has(name) {
847                 name = `${name}`;
848                 validateName(name);
849                 return find(this[MAP], name) !== undefined;
850         }
851
852         /**
853   * Delete all header values given name
854   *
855   * @param   String  name  Header name
856   * @return  Void
857   */
858         delete(name) {
859                 name = `${name}`;
860                 validateName(name);
861                 const key = find(this[MAP], name);
862                 if (key !== undefined) {
863                         delete this[MAP][key];
864                 }
865         }
866
867         /**
868   * Return raw headers (non-spec api)
869   *
870   * @return  Object
871   */
872         raw() {
873                 return this[MAP];
874         }
875
876         /**
877   * Get an iterator on keys.
878   *
879   * @return  Iterator
880   */
881         keys() {
882                 return createHeadersIterator(this, 'key');
883         }
884
885         /**
886   * Get an iterator on values.
887   *
888   * @return  Iterator
889   */
890         values() {
891                 return createHeadersIterator(this, 'value');
892         }
893
894         /**
895   * Get an iterator on entries.
896   *
897   * This is the default iterator of the Headers object.
898   *
899   * @return  Iterator
900   */
901         [Symbol.iterator]() {
902                 return createHeadersIterator(this, 'key+value');
903         }
904 }
905 Headers.prototype.entries = Headers.prototype[Symbol.iterator];
906
907 Object.defineProperty(Headers.prototype, Symbol.toStringTag, {
908         value: 'Headers',
909         writable: false,
910         enumerable: false,
911         configurable: true
912 });
913
914 Object.defineProperties(Headers.prototype, {
915         get: { enumerable: true },
916         forEach: { enumerable: true },
917         set: { enumerable: true },
918         append: { enumerable: true },
919         has: { enumerable: true },
920         delete: { enumerable: true },
921         keys: { enumerable: true },
922         values: { enumerable: true },
923         entries: { enumerable: true }
924 });
925
926 function getHeaders(headers) {
927         let kind = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'key+value';
928
929         const keys = Object.keys(headers[MAP]).sort();
930         return keys.map(kind === 'key' ? function (k) {
931                 return k.toLowerCase();
932         } : kind === 'value' ? function (k) {
933                 return headers[MAP][k].join(', ');
934         } : function (k) {
935                 return [k.toLowerCase(), headers[MAP][k].join(', ')];
936         });
937 }
938
939 const INTERNAL = Symbol('internal');
940
941 function createHeadersIterator(target, kind) {
942         const iterator = Object.create(HeadersIteratorPrototype);
943         iterator[INTERNAL] = {
944                 target,
945                 kind,
946                 index: 0
947         };
948         return iterator;
949 }
950
951 const HeadersIteratorPrototype = Object.setPrototypeOf({
952         next() {
953                 // istanbul ignore if
954                 if (!this || Object.getPrototypeOf(this) !== HeadersIteratorPrototype) {
955                         throw new TypeError('Value of `this` is not a HeadersIterator');
956                 }
957
958                 var _INTERNAL = this[INTERNAL];
959                 const target = _INTERNAL.target,
960                       kind = _INTERNAL.kind,
961                       index = _INTERNAL.index;
962
963                 const values = getHeaders(target, kind);
964                 const len = values.length;
965                 if (index >= len) {
966                         return {
967                                 value: undefined,
968                                 done: true
969                         };
970                 }
971
972                 this[INTERNAL].index = index + 1;
973
974                 return {
975                         value: values[index],
976                         done: false
977                 };
978         }
979 }, Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]())));
980
981 Object.defineProperty(HeadersIteratorPrototype, Symbol.toStringTag, {
982         value: 'HeadersIterator',
983         writable: false,
984         enumerable: false,
985         configurable: true
986 });
987
988 /**
989  * Export the Headers object in a form that Node.js can consume.
990  *
991  * @param   Headers  headers
992  * @return  Object
993  */
994 function exportNodeCompatibleHeaders(headers) {
995         const obj = Object.assign({ __proto__: null }, headers[MAP]);
996
997         // http.request() only supports string as Host header. This hack makes
998         // specifying custom Host header possible.
999         const hostHeaderKey = find(headers[MAP], 'Host');
1000         if (hostHeaderKey !== undefined) {
1001                 obj[hostHeaderKey] = obj[hostHeaderKey][0];
1002         }
1003
1004         return obj;
1005 }
1006
1007 /**
1008  * Create a Headers object from an object of headers, ignoring those that do
1009  * not conform to HTTP grammar productions.
1010  *
1011  * @param   Object  obj  Object of headers
1012  * @return  Headers
1013  */
1014 function createHeadersLenient(obj) {
1015         const headers = new Headers();
1016         for (const name of Object.keys(obj)) {
1017                 if (invalidTokenRegex.test(name)) {
1018                         continue;
1019                 }
1020                 if (Array.isArray(obj[name])) {
1021                         for (const val of obj[name]) {
1022                                 if (invalidHeaderCharRegex.test(val)) {
1023                                         continue;
1024                                 }
1025                                 if (headers[MAP][name] === undefined) {
1026                                         headers[MAP][name] = [val];
1027                                 } else {
1028                                         headers[MAP][name].push(val);
1029                                 }
1030                         }
1031                 } else if (!invalidHeaderCharRegex.test(obj[name])) {
1032                         headers[MAP][name] = [obj[name]];
1033                 }
1034         }
1035         return headers;
1036 }
1037
1038 const INTERNALS$1 = Symbol('Response internals');
1039
1040 // fix an issue where "STATUS_CODES" aren't a named export for node <10
1041 const STATUS_CODES = http.STATUS_CODES;
1042
1043 /**
1044  * Response class
1045  *
1046  * @param   Stream  body  Readable stream
1047  * @param   Object  opts  Response options
1048  * @return  Void
1049  */
1050 class Response {
1051         constructor() {
1052                 let body = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
1053                 let opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1054
1055                 Body.call(this, body, opts);
1056
1057                 const status = opts.status || 200;
1058                 const headers = new Headers(opts.headers);
1059
1060                 if (body != null && !headers.has('Content-Type')) {
1061                         const contentType = extractContentType(body);
1062                         if (contentType) {
1063                                 headers.append('Content-Type', contentType);
1064                         }
1065                 }
1066
1067                 this[INTERNALS$1] = {
1068                         url: opts.url,
1069                         status,
1070                         statusText: opts.statusText || STATUS_CODES[status],
1071                         headers,
1072                         counter: opts.counter
1073                 };
1074         }
1075
1076         get url() {
1077                 return this[INTERNALS$1].url || '';
1078         }
1079
1080         get status() {
1081                 return this[INTERNALS$1].status;
1082         }
1083
1084         /**
1085   * Convenience property representing if the request ended normally
1086   */
1087         get ok() {
1088                 return this[INTERNALS$1].status >= 200 && this[INTERNALS$1].status < 300;
1089         }
1090
1091         get redirected() {
1092                 return this[INTERNALS$1].counter > 0;
1093         }
1094
1095         get statusText() {
1096                 return this[INTERNALS$1].statusText;
1097         }
1098
1099         get headers() {
1100                 return this[INTERNALS$1].headers;
1101         }
1102
1103         /**
1104   * Clone this response
1105   *
1106   * @return  Response
1107   */
1108         clone() {
1109                 return new Response(clone(this), {
1110                         url: this.url,
1111                         status: this.status,
1112                         statusText: this.statusText,
1113                         headers: this.headers,
1114                         ok: this.ok,
1115                         redirected: this.redirected
1116                 });
1117         }
1118 }
1119
1120 Body.mixIn(Response.prototype);
1121
1122 Object.defineProperties(Response.prototype, {
1123         url: { enumerable: true },
1124         status: { enumerable: true },
1125         ok: { enumerable: true },
1126         redirected: { enumerable: true },
1127         statusText: { enumerable: true },
1128         headers: { enumerable: true },
1129         clone: { enumerable: true }
1130 });
1131
1132 Object.defineProperty(Response.prototype, Symbol.toStringTag, {
1133         value: 'Response',
1134         writable: false,
1135         enumerable: false,
1136         configurable: true
1137 });
1138
1139 const INTERNALS$2 = Symbol('Request internals');
1140
1141 // fix an issue where "format", "parse" aren't a named export for node <10
1142 const parse_url = Url.parse;
1143 const format_url = Url.format;
1144
1145 const streamDestructionSupported = 'destroy' in Stream.Readable.prototype;
1146
1147 /**
1148  * Check if a value is an instance of Request.
1149  *
1150  * @param   Mixed   input
1151  * @return  Boolean
1152  */
1153 function isRequest(input) {
1154         return typeof input === 'object' && typeof input[INTERNALS$2] === 'object';
1155 }
1156
1157 function isAbortSignal(signal) {
1158         const proto = signal && typeof signal === 'object' && Object.getPrototypeOf(signal);
1159         return !!(proto && proto.constructor.name === 'AbortSignal');
1160 }
1161
1162 /**
1163  * Request class
1164  *
1165  * @param   Mixed   input  Url or Request instance
1166  * @param   Object  init   Custom options
1167  * @return  Void
1168  */
1169 class Request {
1170         constructor(input) {
1171                 let init = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1172
1173                 let parsedURL;
1174
1175                 // normalize input
1176                 if (!isRequest(input)) {
1177                         if (input && input.href) {
1178                                 // in order to support Node.js' Url objects; though WHATWG's URL objects
1179                                 // will fall into this branch also (since their `toString()` will return
1180                                 // `href` property anyway)
1181                                 parsedURL = parse_url(input.href);
1182                         } else {
1183                                 // coerce input to a string before attempting to parse
1184                                 parsedURL = parse_url(`${input}`);
1185                         }
1186                         input = {};
1187                 } else {
1188                         parsedURL = parse_url(input.url);
1189                 }
1190
1191                 let method = init.method || input.method || 'GET';
1192                 method = method.toUpperCase();
1193
1194                 if ((init.body != null || isRequest(input) && input.body !== null) && (method === 'GET' || method === 'HEAD')) {
1195                         throw new TypeError('Request with GET/HEAD method cannot have body');
1196                 }
1197
1198                 let inputBody = init.body != null ? init.body : isRequest(input) && input.body !== null ? clone(input) : null;
1199
1200                 Body.call(this, inputBody, {
1201                         timeout: init.timeout || input.timeout || 0,
1202                         size: init.size || input.size || 0
1203                 });
1204
1205                 const headers = new Headers(init.headers || input.headers || {});
1206
1207                 if (inputBody != null && !headers.has('Content-Type')) {
1208                         const contentType = extractContentType(inputBody);
1209                         if (contentType) {
1210                                 headers.append('Content-Type', contentType);
1211                         }
1212                 }
1213
1214                 let signal = isRequest(input) ? input.signal : null;
1215                 if ('signal' in init) signal = init.signal;
1216
1217                 if (signal != null && !isAbortSignal(signal)) {
1218                         throw new TypeError('Expected signal to be an instanceof AbortSignal');
1219                 }
1220
1221                 this[INTERNALS$2] = {
1222                         method,
1223                         redirect: init.redirect || input.redirect || 'follow',
1224                         headers,
1225                         parsedURL,
1226                         signal
1227                 };
1228
1229                 // node-fetch-only options
1230                 this.follow = init.follow !== undefined ? init.follow : input.follow !== undefined ? input.follow : 20;
1231                 this.compress = init.compress !== undefined ? init.compress : input.compress !== undefined ? input.compress : true;
1232                 this.counter = init.counter || input.counter || 0;
1233                 this.agent = init.agent || input.agent;
1234         }
1235
1236         get method() {
1237                 return this[INTERNALS$2].method;
1238         }
1239
1240         get url() {
1241                 return format_url(this[INTERNALS$2].parsedURL);
1242         }
1243
1244         get headers() {
1245                 return this[INTERNALS$2].headers;
1246         }
1247
1248         get redirect() {
1249                 return this[INTERNALS$2].redirect;
1250         }
1251
1252         get signal() {
1253                 return this[INTERNALS$2].signal;
1254         }
1255
1256         /**
1257   * Clone this request
1258   *
1259   * @return  Request
1260   */
1261         clone() {
1262                 return new Request(this);
1263         }
1264 }
1265
1266 Body.mixIn(Request.prototype);
1267
1268 Object.defineProperty(Request.prototype, Symbol.toStringTag, {
1269         value: 'Request',
1270         writable: false,
1271         enumerable: false,
1272         configurable: true
1273 });
1274
1275 Object.defineProperties(Request.prototype, {
1276         method: { enumerable: true },
1277         url: { enumerable: true },
1278         headers: { enumerable: true },
1279         redirect: { enumerable: true },
1280         clone: { enumerable: true },
1281         signal: { enumerable: true }
1282 });
1283
1284 /**
1285  * Convert a Request to Node.js http request options.
1286  *
1287  * @param   Request  A Request instance
1288  * @return  Object   The options object to be passed to http.request
1289  */
1290 function getNodeRequestOptions(request) {
1291         const parsedURL = request[INTERNALS$2].parsedURL;
1292         const headers = new Headers(request[INTERNALS$2].headers);
1293
1294         // fetch step 1.3
1295         if (!headers.has('Accept')) {
1296                 headers.set('Accept', '*/*');
1297         }
1298
1299         // Basic fetch
1300         if (!parsedURL.protocol || !parsedURL.hostname) {
1301                 throw new TypeError('Only absolute URLs are supported');
1302         }
1303
1304         if (!/^https?:$/.test(parsedURL.protocol)) {
1305                 throw new TypeError('Only HTTP(S) protocols are supported');
1306         }
1307
1308         if (request.signal && request.body instanceof Stream.Readable && !streamDestructionSupported) {
1309                 throw new Error('Cancellation of streamed requests with AbortSignal is not supported in node < 8');
1310         }
1311
1312         // HTTP-network-or-cache fetch steps 2.4-2.7
1313         let contentLengthValue = null;
1314         if (request.body == null && /^(POST|PUT)$/i.test(request.method)) {
1315                 contentLengthValue = '0';
1316         }
1317         if (request.body != null) {
1318                 const totalBytes = getTotalBytes(request);
1319                 if (typeof totalBytes === 'number') {
1320                         contentLengthValue = String(totalBytes);
1321                 }
1322         }
1323         if (contentLengthValue) {
1324                 headers.set('Content-Length', contentLengthValue);
1325         }
1326
1327         // HTTP-network-or-cache fetch step 2.11
1328         if (!headers.has('User-Agent')) {
1329                 headers.set('User-Agent', 'node-fetch/1.0 (+https://github.com/bitinn/node-fetch)');
1330         }
1331
1332         // HTTP-network-or-cache fetch step 2.15
1333         if (request.compress && !headers.has('Accept-Encoding')) {
1334                 headers.set('Accept-Encoding', 'gzip,deflate');
1335         }
1336
1337         let agent = request.agent;
1338         if (typeof agent === 'function') {
1339                 agent = agent(parsedURL);
1340         }
1341
1342         if (!headers.has('Connection') && !agent) {
1343                 headers.set('Connection', 'close');
1344         }
1345
1346         // HTTP-network fetch step 4.2
1347         // chunked encoding is handled by Node.js
1348
1349         return Object.assign({}, parsedURL, {
1350                 method: request.method,
1351                 headers: exportNodeCompatibleHeaders(headers),
1352                 agent
1353         });
1354 }
1355
1356 /**
1357  * abort-error.js
1358  *
1359  * AbortError interface for cancelled requests
1360  */
1361
1362 /**
1363  * Create AbortError instance
1364  *
1365  * @param   String      message      Error message for human
1366  * @return  AbortError
1367  */
1368 function AbortError(message) {
1369   Error.call(this, message);
1370
1371   this.type = 'aborted';
1372   this.message = message;
1373
1374   // hide custom error implementation details from end-users
1375   Error.captureStackTrace(this, this.constructor);
1376 }
1377
1378 AbortError.prototype = Object.create(Error.prototype);
1379 AbortError.prototype.constructor = AbortError;
1380 AbortError.prototype.name = 'AbortError';
1381
1382 // fix an issue where "PassThrough", "resolve" aren't a named export for node <10
1383 const PassThrough$1 = Stream.PassThrough;
1384 const resolve_url = Url.resolve;
1385
1386 /**
1387  * Fetch function
1388  *
1389  * @param   Mixed    url   Absolute url or Request instance
1390  * @param   Object   opts  Fetch options
1391  * @return  Promise
1392  */
1393 function fetch(url, opts) {
1394
1395         // allow custom promise
1396         if (!fetch.Promise) {
1397                 throw new Error('native promise missing, set fetch.Promise to your favorite alternative');
1398         }
1399
1400         Body.Promise = fetch.Promise;
1401
1402         // wrap http.request into fetch
1403         return new fetch.Promise(function (resolve, reject) {
1404                 // build request object
1405                 const request = new Request(url, opts);
1406                 const options = getNodeRequestOptions(request);
1407
1408                 const send = (options.protocol === 'https:' ? https : http).request;
1409                 const signal = request.signal;
1410
1411                 let response = null;
1412
1413                 const abort = function abort() {
1414                         let error = new AbortError('The user aborted a request.');
1415                         reject(error);
1416                         if (request.body && request.body instanceof Stream.Readable) {
1417                                 request.body.destroy(error);
1418                         }
1419                         if (!response || !response.body) return;
1420                         response.body.emit('error', error);
1421                 };
1422
1423                 if (signal && signal.aborted) {
1424                         abort();
1425                         return;
1426                 }
1427
1428                 const abortAndFinalize = function abortAndFinalize() {
1429                         abort();
1430                         finalize();
1431                 };
1432
1433                 // send request
1434                 const req = send(options);
1435                 let reqTimeout;
1436
1437                 if (signal) {
1438                         signal.addEventListener('abort', abortAndFinalize);
1439                 }
1440
1441                 function finalize() {
1442                         req.abort();
1443                         if (signal) signal.removeEventListener('abort', abortAndFinalize);
1444                         clearTimeout(reqTimeout);
1445                 }
1446
1447                 if (request.timeout) {
1448                         req.once('socket', function (socket) {
1449                                 reqTimeout = setTimeout(function () {
1450                                         reject(new FetchError(`network timeout at: ${request.url}`, 'request-timeout'));
1451                                         finalize();
1452                                 }, request.timeout);
1453                         });
1454                 }
1455
1456                 req.on('error', function (err) {
1457                         reject(new FetchError(`request to ${request.url} failed, reason: ${err.message}`, 'system', err));
1458                         finalize();
1459                 });
1460
1461                 req.on('response', function (res) {
1462                         clearTimeout(reqTimeout);
1463
1464                         const headers = createHeadersLenient(res.headers);
1465
1466                         // HTTP fetch step 5
1467                         if (fetch.isRedirect(res.statusCode)) {
1468                                 // HTTP fetch step 5.2
1469                                 const location = headers.get('Location');
1470
1471                                 // HTTP fetch step 5.3
1472                                 const locationURL = location === null ? null : resolve_url(request.url, location);
1473
1474                                 // HTTP fetch step 5.5
1475                                 switch (request.redirect) {
1476                                         case 'error':
1477                                                 reject(new FetchError(`uri requested responds with a redirect, redirect mode is set to error: ${request.url}`, 'no-redirect'));
1478                                                 finalize();
1479                                                 return;
1480                                         case 'manual':
1481                                                 // node-fetch-specific step: make manual redirect a bit easier to use by setting the Location header value to the resolved URL.
1482                                                 if (locationURL !== null) {
1483                                                         // handle corrupted header
1484                                                         try {
1485                                                                 headers.set('Location', locationURL);
1486                                                         } catch (err) {
1487                                                                 // istanbul ignore next: nodejs server prevent invalid response headers, we can't test this through normal request
1488                                                                 reject(err);
1489                                                         }
1490                                                 }
1491                                                 break;
1492                                         case 'follow':
1493                                                 // HTTP-redirect fetch step 2
1494                                                 if (locationURL === null) {
1495                                                         break;
1496                                                 }
1497
1498                                                 // HTTP-redirect fetch step 5
1499                                                 if (request.counter >= request.follow) {
1500                                                         reject(new FetchError(`maximum redirect reached at: ${request.url}`, 'max-redirect'));
1501                                                         finalize();
1502                                                         return;
1503                                                 }
1504
1505                                                 // HTTP-redirect fetch step 6 (counter increment)
1506                                                 // Create a new Request object.
1507                                                 const requestOpts = {
1508                                                         headers: new Headers(request.headers),
1509                                                         follow: request.follow,
1510                                                         counter: request.counter + 1,
1511                                                         agent: request.agent,
1512                                                         compress: request.compress,
1513                                                         method: request.method,
1514                                                         body: request.body,
1515                                                         signal: request.signal,
1516                                                         timeout: request.timeout,
1517                                                         size: request.size
1518                                                 };
1519
1520                                                 // HTTP-redirect fetch step 9
1521                                                 if (res.statusCode !== 303 && request.body && getTotalBytes(request) === null) {
1522                                                         reject(new FetchError('Cannot follow redirect with body being a readable stream', 'unsupported-redirect'));
1523                                                         finalize();
1524                                                         return;
1525                                                 }
1526
1527                                                 // HTTP-redirect fetch step 11
1528                                                 if (res.statusCode === 303 || (res.statusCode === 301 || res.statusCode === 302) && request.method === 'POST') {
1529                                                         requestOpts.method = 'GET';
1530                                                         requestOpts.body = undefined;
1531                                                         requestOpts.headers.delete('content-length');
1532                                                 }
1533
1534                                                 // HTTP-redirect fetch step 15
1535                                                 resolve(fetch(new Request(locationURL, requestOpts)));
1536                                                 finalize();
1537                                                 return;
1538                                 }
1539                         }
1540
1541                         // prepare response
1542                         res.once('end', function () {
1543                                 if (signal) signal.removeEventListener('abort', abortAndFinalize);
1544                         });
1545                         let body = res.pipe(new PassThrough$1());
1546
1547                         const response_options = {
1548                                 url: request.url,
1549                                 status: res.statusCode,
1550                                 statusText: res.statusMessage,
1551                                 headers: headers,
1552                                 size: request.size,
1553                                 timeout: request.timeout,
1554                                 counter: request.counter
1555                         };
1556
1557                         // HTTP-network fetch step 12.1.1.3
1558                         const codings = headers.get('Content-Encoding');
1559
1560                         // HTTP-network fetch step 12.1.1.4: handle content codings
1561
1562                         // in following scenarios we ignore compression support
1563                         // 1. compression support is disabled
1564                         // 2. HEAD request
1565                         // 3. no Content-Encoding header
1566                         // 4. no content response (204)
1567                         // 5. content not modified response (304)
1568                         if (!request.compress || request.method === 'HEAD' || codings === null || res.statusCode === 204 || res.statusCode === 304) {
1569                                 response = new Response(body, response_options);
1570                                 resolve(response);
1571                                 return;
1572                         }
1573
1574                         // For Node v6+
1575                         // Be less strict when decoding compressed responses, since sometimes
1576                         // servers send slightly invalid responses that are still accepted
1577                         // by common browsers.
1578                         // Always using Z_SYNC_FLUSH is what cURL does.
1579                         const zlibOptions = {
1580                                 flush: zlib.Z_SYNC_FLUSH,
1581                                 finishFlush: zlib.Z_SYNC_FLUSH
1582                         };
1583
1584                         // for gzip
1585                         if (codings == 'gzip' || codings == 'x-gzip') {
1586                                 body = body.pipe(zlib.createGunzip(zlibOptions));
1587                                 response = new Response(body, response_options);
1588                                 resolve(response);
1589                                 return;
1590                         }
1591
1592                         // for deflate
1593                         if (codings == 'deflate' || codings == 'x-deflate') {
1594                                 // handle the infamous raw deflate response from old servers
1595                                 // a hack for old IIS and Apache servers
1596                                 const raw = res.pipe(new PassThrough$1());
1597                                 raw.once('data', function (chunk) {
1598                                         // see http://stackoverflow.com/questions/37519828
1599                                         if ((chunk[0] & 0x0F) === 0x08) {
1600                                                 body = body.pipe(zlib.createInflate());
1601                                         } else {
1602                                                 body = body.pipe(zlib.createInflateRaw());
1603                                         }
1604                                         response = new Response(body, response_options);
1605                                         resolve(response);
1606                                 });
1607                                 return;
1608                         }
1609
1610                         // for br
1611                         if (codings == 'br' && typeof zlib.createBrotliDecompress === 'function') {
1612                                 body = body.pipe(zlib.createBrotliDecompress());
1613                                 response = new Response(body, response_options);
1614                                 resolve(response);
1615                                 return;
1616                         }
1617
1618                         // otherwise, use response as-is
1619                         response = new Response(body, response_options);
1620                         resolve(response);
1621                 });
1622
1623                 writeToStream(req, request);
1624         });
1625 }
1626 /**
1627  * Redirect code matching
1628  *
1629  * @param   Number   code  Status code
1630  * @return  Boolean
1631  */
1632 fetch.isRedirect = function (code) {
1633         return code === 301 || code === 302 || code === 303 || code === 307 || code === 308;
1634 };
1635
1636 // expose Promise
1637 fetch.Promise = global.Promise;
1638
1639 export default fetch;
1640 export { Headers, Request, Response, FetchError };