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