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