이세린

Trying to embed random puppy, img not working

Showing 80 changed files with 10159 additions and 0 deletions
1 +'use strict';
2 +
3 +module.exports = Error.captureStackTrace || function (error) {
4 + var container = new Error();
5 +
6 + Object.defineProperty(error, 'stack', {
7 + configurable: true,
8 + get: function getStack() {
9 + var stack = container.stack;
10 +
11 + Object.defineProperty(this, 'stack', {
12 + value: stack
13 + });
14 +
15 + return stack;
16 + }
17 + });
18 +};
1 +The MIT License (MIT)
2 +
3 +Copyright (c) Vsevolod Strukchinsky <floatdrop@gmail.com> (github.com/floatdrop)
4 +
5 +Permission is hereby granted, free of charge, to any person obtaining a copy
6 +of this software and associated documentation files (the "Software"), to deal
7 +in the Software without restriction, including without limitation the rights
8 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 +copies of the Software, and to permit persons to whom the Software is
10 +furnished to do so, subject to the following conditions:
11 +
12 +The above copyright notice and this permission notice shall be included in
13 +all copies or substantial portions of the Software.
14 +
15 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 +THE SOFTWARE.
1 +{
2 + "name": "capture-stack-trace",
3 + "version": "1.0.1",
4 + "description": "Error.captureStackTrace ponyfill",
5 + "license": "MIT",
6 + "repository": "floatdrop/capture-stack-trace",
7 + "author": {
8 + "name": "Vsevolod Strukchinsky",
9 + "email": "floatdrop@gmail.com",
10 + "url": "github.com/floatdrop"
11 + },
12 + "engines": {
13 + "node": ">=0.10.0"
14 + },
15 + "scripts": {
16 + "test": "mocha"
17 + },
18 + "files": [
19 + "index.js"
20 + ],
21 + "keywords": [
22 + "Error",
23 + "captureStackTrace"
24 + ],
25 + "dependencies": {},
26 + "devDependencies": {
27 + "mocha": "*"
28 + }
29 +}
1 +# capture-stack-trace [![Build Status](https://travis-ci.org/floatdrop/capture-stack-trace.svg?branch=master)](https://travis-ci.org/floatdrop/capture-stack-trace)
2 +
3 +> Ponyfill for Error.captureStackTrace
4 +
5 +
6 +## Install
7 +
8 +```
9 +$ npm install --save capture-stack-trace
10 +```
11 +
12 +
13 +## Usage
14 +
15 +```js
16 +var captureStackTrace = require('capture-stack-trace');
17 +
18 +captureStackTrace({});
19 +// => {stack: ...}
20 +```
21 +
22 +
23 +## API
24 +
25 +### captureStackTrace(error)
26 +
27 +#### error
28 +
29 +*Required*
30 +Type: `Object`
31 +
32 +Target Object, that will recieve stack property.
33 +
34 +## License
35 +
36 +MIT © [Vsevolod Strukchinsky](http://github.com/floatdrop)
1 +'use strict';
2 +var captureStackTrace = require('capture-stack-trace');
3 +
4 +function inherits(ctor, superCtor) {
5 + ctor.super_ = superCtor;
6 + ctor.prototype = Object.create(superCtor.prototype, {
7 + constructor: {
8 + value: ctor,
9 + enumerable: false,
10 + writable: true,
11 + configurable: true
12 + }
13 + });
14 +}
15 +
16 +module.exports = function createErrorClass(className, setup) {
17 + if (typeof className !== 'string') {
18 + throw new TypeError('Expected className to be a string');
19 + }
20 +
21 + if (/[^0-9a-zA-Z_$]/.test(className)) {
22 + throw new Error('className contains invalid characters');
23 + }
24 +
25 + setup = setup || function (message) {
26 + this.message = message;
27 + };
28 +
29 + var ErrorClass = function () {
30 + Object.defineProperty(this, 'name', {
31 + configurable: true,
32 + value: className,
33 + writable: true
34 + });
35 +
36 + captureStackTrace(this, this.constructor);
37 +
38 + setup.apply(this, arguments);
39 + };
40 +
41 + inherits(ErrorClass, Error);
42 +
43 + return ErrorClass;
44 +};
1 +The MIT License (MIT)
2 +
3 +Copyright (c) Vsevolod Strukchinsky <floatdrop@gmail.com> (github.com/floatdrop)
4 +
5 +Permission is hereby granted, free of charge, to any person obtaining a copy
6 +of this software and associated documentation files (the "Software"), to deal
7 +in the Software without restriction, including without limitation the rights
8 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 +copies of the Software, and to permit persons to whom the Software is
10 +furnished to do so, subject to the following conditions:
11 +
12 +The above copyright notice and this permission notice shall be included in
13 +all copies or substantial portions of the Software.
14 +
15 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 +THE SOFTWARE.
1 +{
2 + "name": "create-error-class",
3 + "version": "3.0.2",
4 + "description": "Create Error classes",
5 + "license": "MIT",
6 + "repository": "floatdrop/create-error-class",
7 + "author": {
8 + "name": "Vsevolod Strukchinsky",
9 + "email": "floatdrop@gmail.com",
10 + "url": "github.com/floatdrop"
11 + },
12 + "engines": {
13 + "node": ">=0.10.0"
14 + },
15 + "scripts": {
16 + "test": "mocha"
17 + },
18 + "files": [
19 + "index.js"
20 + ],
21 + "keywords": [
22 + ""
23 + ],
24 + "dependencies": {
25 + "capture-stack-trace": "^1.0.0"
26 + },
27 + "devDependencies": {
28 + "mocha": "*"
29 + }
30 +}
1 +# create-error-class [![Build Status](https://travis-ci.org/floatdrop/create-error-class.svg?branch=master)](https://travis-ci.org/floatdrop/create-error-class)
2 +
3 +> Create error class
4 +
5 +
6 +## Install
7 +
8 +```
9 +$ npm install --save create-error-class
10 +```
11 +
12 +
13 +## Usage
14 +
15 +```js
16 +var createErrorClass = require('create-error-class');
17 +
18 +var HTTPError = createErrorClass('HTTPError', function (props) {
19 + this.message = 'Status code is ' + props.statusCode;
20 +});
21 +
22 +throw new HTTPError({statusCode: 404});
23 +```
24 +
25 +
26 +## API
27 +
28 +### createErrorClass(className, [setup])
29 +
30 +Return constructor of Errors with `className`.
31 +
32 +#### className
33 +
34 +*Required*
35 +Type: `string`
36 +
37 +Class name of Error Object. Should contain characters from `[0-9a-zA-Z_$]` range.
38 +
39 +#### setup
40 +Type: `function`
41 +
42 +Setup function, that will be called after each Error object is created from constructor with context of Error object.
43 +
44 +By default `setup` function sets `this.message` as first argument:
45 +
46 +```js
47 +var MyError = createErrorClass('MyError');
48 +
49 +new MyError('Something gone wrong!').message; // => 'Something gone wrong!'
50 +```
51 +
52 +## License
53 +
54 +MIT © [Vsevolod Strukchinsky](http://github.com/floatdrop)
1 +The MIT License (MIT)
2 +
3 +Copyright (c) 2016 David Frank
4 +
5 +Permission is hereby granted, free of charge, to any person obtaining a copy
6 +of this software and associated documentation files (the "Software"), to deal
7 +in the Software without restriction, including without limitation the rights
8 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 +copies of the Software, and to permit persons to whom the Software is
10 +furnished to do so, subject to the following conditions:
11 +
12 +The above copyright notice and this permission notice shall be included in all
13 +copies or substantial portions of the Software.
14 +
15 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 +SOFTWARE.
22 +
1 +node-fetch
2 +==========
3 +
4 +[![npm version][npm-image]][npm-url]
5 +[![build status][travis-image]][travis-url]
6 +[![coverage status][codecov-image]][codecov-url]
7 +[![install size][install-size-image]][install-size-url]
8 +[![Discord][discord-image]][discord-url]
9 +
10 +A light-weight module that brings `window.fetch` to Node.js
11 +
12 +(We are looking for [v2 maintainers and collaborators](https://github.com/bitinn/node-fetch/issues/567))
13 +
14 +[![Backers][opencollective-image]][opencollective-url]
15 +
16 +<!-- TOC -->
17 +
18 +- [Motivation](#motivation)
19 +- [Features](#features)
20 +- [Difference from client-side fetch](#difference-from-client-side-fetch)
21 +- [Installation](#installation)
22 +- [Loading and configuring the module](#loading-and-configuring-the-module)
23 +- [Common Usage](#common-usage)
24 + - [Plain text or HTML](#plain-text-or-html)
25 + - [JSON](#json)
26 + - [Simple Post](#simple-post)
27 + - [Post with JSON](#post-with-json)
28 + - [Post with form parameters](#post-with-form-parameters)
29 + - [Handling exceptions](#handling-exceptions)
30 + - [Handling client and server errors](#handling-client-and-server-errors)
31 +- [Advanced Usage](#advanced-usage)
32 + - [Streams](#streams)
33 + - [Buffer](#buffer)
34 + - [Accessing Headers and other Meta data](#accessing-headers-and-other-meta-data)
35 + - [Extract Set-Cookie Header](#extract-set-cookie-header)
36 + - [Post data using a file stream](#post-data-using-a-file-stream)
37 + - [Post with form-data (detect multipart)](#post-with-form-data-detect-multipart)
38 + - [Request cancellation with AbortSignal](#request-cancellation-with-abortsignal)
39 +- [API](#api)
40 + - [fetch(url[, options])](#fetchurl-options)
41 + - [Options](#options)
42 + - [Class: Request](#class-request)
43 + - [Class: Response](#class-response)
44 + - [Class: Headers](#class-headers)
45 + - [Interface: Body](#interface-body)
46 + - [Class: FetchError](#class-fetcherror)
47 +- [License](#license)
48 +- [Acknowledgement](#acknowledgement)
49 +
50 +<!-- /TOC -->
51 +
52 +## Motivation
53 +
54 +Instead of implementing `XMLHttpRequest` in Node.js to run browser-specific [Fetch polyfill](https://github.com/github/fetch), why not go from native `http` to `fetch` API directly? Hence, `node-fetch`, minimal code for a `window.fetch` compatible API on Node.js runtime.
55 +
56 +See Matt Andrews' [isomorphic-fetch](https://github.com/matthew-andrews/isomorphic-fetch) or Leonardo Quixada's [cross-fetch](https://github.com/lquixada/cross-fetch) for isomorphic usage (exports `node-fetch` for server-side, `whatwg-fetch` for client-side).
57 +
58 +## Features
59 +
60 +- Stay consistent with `window.fetch` API.
61 +- Make conscious trade-off when following [WHATWG fetch spec][whatwg-fetch] and [stream spec](https://streams.spec.whatwg.org/) implementation details, document known differences.
62 +- Use native promise but allow substituting it with [insert your favorite promise library].
63 +- Use native Node streams for body on both request and response.
64 +- Decode content encoding (gzip/deflate) properly and convert string output (such as `res.text()` and `res.json()`) to UTF-8 automatically.
65 +- Useful extensions such as timeout, redirect limit, response size limit, [explicit errors](ERROR-HANDLING.md) for troubleshooting.
66 +
67 +## Difference from client-side fetch
68 +
69 +- See [Known Differences](LIMITS.md) for details.
70 +- If you happen to use a missing feature that `window.fetch` offers, feel free to open an issue.
71 +- Pull requests are welcomed too!
72 +
73 +## Installation
74 +
75 +Current stable release (`2.x`)
76 +
77 +```sh
78 +$ npm install node-fetch
79 +```
80 +
81 +## Loading and configuring the module
82 +We suggest you load the module via `require` until the stabilization of ES modules in node:
83 +```js
84 +const fetch = require('node-fetch');
85 +```
86 +
87 +If you are using a Promise library other than native, set it through `fetch.Promise`:
88 +```js
89 +const Bluebird = require('bluebird');
90 +
91 +fetch.Promise = Bluebird;
92 +```
93 +
94 +## Common Usage
95 +
96 +NOTE: The documentation below is up-to-date with `2.x` releases; see the [`1.x` readme](https://github.com/bitinn/node-fetch/blob/1.x/README.md), [changelog](https://github.com/bitinn/node-fetch/blob/1.x/CHANGELOG.md) and [2.x upgrade guide](UPGRADE-GUIDE.md) for the differences.
97 +
98 +#### Plain text or HTML
99 +```js
100 +fetch('https://github.com/')
101 + .then(res => res.text())
102 + .then(body => console.log(body));
103 +```
104 +
105 +#### JSON
106 +
107 +```js
108 +
109 +fetch('https://api.github.com/users/github')
110 + .then(res => res.json())
111 + .then(json => console.log(json));
112 +```
113 +
114 +#### Simple Post
115 +```js
116 +fetch('https://httpbin.org/post', { method: 'POST', body: 'a=1' })
117 + .then(res => res.json()) // expecting a json response
118 + .then(json => console.log(json));
119 +```
120 +
121 +#### Post with JSON
122 +
123 +```js
124 +const body = { a: 1 };
125 +
126 +fetch('https://httpbin.org/post', {
127 + method: 'post',
128 + body: JSON.stringify(body),
129 + headers: { 'Content-Type': 'application/json' },
130 + })
131 + .then(res => res.json())
132 + .then(json => console.log(json));
133 +```
134 +
135 +#### Post with form parameters
136 +`URLSearchParams` is available in Node.js as of v7.5.0. See [official documentation](https://nodejs.org/api/url.html#url_class_urlsearchparams) for more usage methods.
137 +
138 +NOTE: The `Content-Type` header is only set automatically to `x-www-form-urlencoded` when an instance of `URLSearchParams` is given as such:
139 +
140 +```js
141 +const { URLSearchParams } = require('url');
142 +
143 +const params = new URLSearchParams();
144 +params.append('a', 1);
145 +
146 +fetch('https://httpbin.org/post', { method: 'POST', body: params })
147 + .then(res => res.json())
148 + .then(json => console.log(json));
149 +```
150 +
151 +#### Handling exceptions
152 +NOTE: 3xx-5xx responses are *NOT* exceptions and should be handled in `then()`; see the next section for more information.
153 +
154 +Adding a catch to the fetch promise chain will catch *all* exceptions, such as errors originating from node core libraries, network errors and operational errors, which are instances of FetchError. See the [error handling document](ERROR-HANDLING.md) for more details.
155 +
156 +```js
157 +fetch('https://domain.invalid/')
158 + .catch(err => console.error(err));
159 +```
160 +
161 +#### Handling client and server errors
162 +It is common to create a helper function to check that the response contains no client (4xx) or server (5xx) error responses:
163 +
164 +```js
165 +function checkStatus(res) {
166 + if (res.ok) { // res.status >= 200 && res.status < 300
167 + return res;
168 + } else {
169 + throw MyCustomError(res.statusText);
170 + }
171 +}
172 +
173 +fetch('https://httpbin.org/status/400')
174 + .then(checkStatus)
175 + .then(res => console.log('will not get here...'))
176 +```
177 +
178 +## Advanced Usage
179 +
180 +#### Streams
181 +The "Node.js way" is to use streams when possible:
182 +
183 +```js
184 +fetch('https://assets-cdn.github.com/images/modules/logos_page/Octocat.png')
185 + .then(res => {
186 + const dest = fs.createWriteStream('./octocat.png');
187 + res.body.pipe(dest);
188 + });
189 +```
190 +
191 +#### Buffer
192 +If you prefer to cache binary data in full, use buffer(). (NOTE: `buffer()` is a `node-fetch`-only API)
193 +
194 +```js
195 +const fileType = require('file-type');
196 +
197 +fetch('https://assets-cdn.github.com/images/modules/logos_page/Octocat.png')
198 + .then(res => res.buffer())
199 + .then(buffer => fileType(buffer))
200 + .then(type => { /* ... */ });
201 +```
202 +
203 +#### Accessing Headers and other Meta data
204 +```js
205 +fetch('https://github.com/')
206 + .then(res => {
207 + console.log(res.ok);
208 + console.log(res.status);
209 + console.log(res.statusText);
210 + console.log(res.headers.raw());
211 + console.log(res.headers.get('content-type'));
212 + });
213 +```
214 +
215 +#### Extract Set-Cookie Header
216 +
217 +Unlike browsers, you can access raw `Set-Cookie` headers manually using `Headers.raw()`. This is a `node-fetch` only API.
218 +
219 +```js
220 +fetch(url).then(res => {
221 + // returns an array of values, instead of a string of comma-separated values
222 + console.log(res.headers.raw()['set-cookie']);
223 +});
224 +```
225 +
226 +#### Post data using a file stream
227 +
228 +```js
229 +const { createReadStream } = require('fs');
230 +
231 +const stream = createReadStream('input.txt');
232 +
233 +fetch('https://httpbin.org/post', { method: 'POST', body: stream })
234 + .then(res => res.json())
235 + .then(json => console.log(json));
236 +```
237 +
238 +#### Post with form-data (detect multipart)
239 +
240 +```js
241 +const FormData = require('form-data');
242 +
243 +const form = new FormData();
244 +form.append('a', 1);
245 +
246 +fetch('https://httpbin.org/post', { method: 'POST', body: form })
247 + .then(res => res.json())
248 + .then(json => console.log(json));
249 +
250 +// OR, using custom headers
251 +// NOTE: getHeaders() is non-standard API
252 +
253 +const form = new FormData();
254 +form.append('a', 1);
255 +
256 +const options = {
257 + method: 'POST',
258 + body: form,
259 + headers: form.getHeaders()
260 +}
261 +
262 +fetch('https://httpbin.org/post', options)
263 + .then(res => res.json())
264 + .then(json => console.log(json));
265 +```
266 +
267 +#### Request cancellation with AbortSignal
268 +
269 +> NOTE: You may cancel streamed requests only on Node >= v8.0.0
270 +
271 +You may cancel requests with `AbortController`. A suggested implementation is [`abort-controller`](https://www.npmjs.com/package/abort-controller).
272 +
273 +An example of timing out a request after 150ms could be achieved as the following:
274 +
275 +```js
276 +import AbortController from 'abort-controller';
277 +
278 +const controller = new AbortController();
279 +const timeout = setTimeout(
280 + () => { controller.abort(); },
281 + 150,
282 +);
283 +
284 +fetch(url, { signal: controller.signal })
285 + .then(res => res.json())
286 + .then(
287 + data => {
288 + useData(data)
289 + },
290 + err => {
291 + if (err.name === 'AbortError') {
292 + // request was aborted
293 + }
294 + },
295 + )
296 + .finally(() => {
297 + clearTimeout(timeout);
298 + });
299 +```
300 +
301 +See [test cases](https://github.com/bitinn/node-fetch/blob/master/test/test.js) for more examples.
302 +
303 +
304 +## API
305 +
306 +### fetch(url[, options])
307 +
308 +- `url` A string representing the URL for fetching
309 +- `options` [Options](#fetch-options) for the HTTP(S) request
310 +- Returns: <code>Promise&lt;[Response](#class-response)&gt;</code>
311 +
312 +Perform an HTTP(S) fetch.
313 +
314 +`url` should be an absolute url, such as `https://example.com/`. A path-relative URL (`/file/under/root`) or protocol-relative URL (`//can-be-http-or-https.com/`) will result in a rejected `Promise`.
315 +
316 +<a id="fetch-options"></a>
317 +### Options
318 +
319 +The default values are shown after each option key.
320 +
321 +```js
322 +{
323 + // These properties are part of the Fetch Standard
324 + method: 'GET',
325 + headers: {}, // request headers. format is the identical to that accepted by the Headers constructor (see below)
326 + body: null, // request body. can be null, a string, a Buffer, a Blob, or a Node.js Readable stream
327 + redirect: 'follow', // set to `manual` to extract redirect headers, `error` to reject redirect
328 + signal: null, // pass an instance of AbortSignal to optionally abort requests
329 +
330 + // The following properties are node-fetch extensions
331 + follow: 20, // maximum redirect count. 0 to not follow redirect
332 + timeout: 0, // req/res timeout in ms, it resets on redirect. 0 to disable (OS limit applies). Signal is recommended instead.
333 + compress: true, // support gzip/deflate content encoding. false to disable
334 + size: 0, // maximum response body size in bytes. 0 to disable
335 + agent: null // http(s).Agent instance or function that returns an instance (see below)
336 +}
337 +```
338 +
339 +##### Default Headers
340 +
341 +If no values are set, the following request headers will be sent automatically:
342 +
343 +Header | Value
344 +------------------- | --------------------------------------------------------
345 +`Accept-Encoding` | `gzip,deflate` _(when `options.compress === true`)_
346 +`Accept` | `*/*`
347 +`Connection` | `close` _(when no `options.agent` is present)_
348 +`Content-Length` | _(automatically calculated, if possible)_
349 +`Transfer-Encoding` | `chunked` _(when `req.body` is a stream)_
350 +`User-Agent` | `node-fetch/1.0 (+https://github.com/bitinn/node-fetch)`
351 +
352 +Note: when `body` is a `Stream`, `Content-Length` is not set automatically.
353 +
354 +##### Custom Agent
355 +
356 +The `agent` option allows you to specify networking related options which are out of the scope of Fetch, including and not limited to the following:
357 +
358 +- Support self-signed certificate
359 +- Use only IPv4 or IPv6
360 +- Custom DNS Lookup
361 +
362 +See [`http.Agent`](https://nodejs.org/api/http.html#http_new_agent_options) for more information.
363 +
364 +In addition, the `agent` option accepts a function that returns `http`(s)`.Agent` instance given current [URL](https://nodejs.org/api/url.html), this is useful during a redirection chain across HTTP and HTTPS protocol.
365 +
366 +```js
367 +const httpAgent = new http.Agent({
368 + keepAlive: true
369 +});
370 +const httpsAgent = new https.Agent({
371 + keepAlive: true
372 +});
373 +
374 +const options = {
375 + agent: function (_parsedURL) {
376 + if (_parsedURL.protocol == 'http:') {
377 + return httpAgent;
378 + } else {
379 + return httpsAgent;
380 + }
381 + }
382 +}
383 +```
384 +
385 +<a id="class-request"></a>
386 +### Class: Request
387 +
388 +An HTTP(S) request containing information about URL, method, headers, and the body. This class implements the [Body](#iface-body) interface.
389 +
390 +Due to the nature of Node.js, the following properties are not implemented at this moment:
391 +
392 +- `type`
393 +- `destination`
394 +- `referrer`
395 +- `referrerPolicy`
396 +- `mode`
397 +- `credentials`
398 +- `cache`
399 +- `integrity`
400 +- `keepalive`
401 +
402 +The following node-fetch extension properties are provided:
403 +
404 +- `follow`
405 +- `compress`
406 +- `counter`
407 +- `agent`
408 +
409 +See [options](#fetch-options) for exact meaning of these extensions.
410 +
411 +#### new Request(input[, options])
412 +
413 +<small>*(spec-compliant)*</small>
414 +
415 +- `input` A string representing a URL, or another `Request` (which will be cloned)
416 +- `options` [Options][#fetch-options] for the HTTP(S) request
417 +
418 +Constructs a new `Request` object. The constructor is identical to that in the [browser](https://developer.mozilla.org/en-US/docs/Web/API/Request/Request).
419 +
420 +In most cases, directly `fetch(url, options)` is simpler than creating a `Request` object.
421 +
422 +<a id="class-response"></a>
423 +### Class: Response
424 +
425 +An HTTP(S) response. This class implements the [Body](#iface-body) interface.
426 +
427 +The following properties are not implemented in node-fetch at this moment:
428 +
429 +- `Response.error()`
430 +- `Response.redirect()`
431 +- `type`
432 +- `trailer`
433 +
434 +#### new Response([body[, options]])
435 +
436 +<small>*(spec-compliant)*</small>
437 +
438 +- `body` A `String` or [`Readable` stream][node-readable]
439 +- `options` A [`ResponseInit`][response-init] options dictionary
440 +
441 +Constructs a new `Response` object. The constructor is identical to that in the [browser](https://developer.mozilla.org/en-US/docs/Web/API/Response/Response).
442 +
443 +Because Node.js does not implement service workers (for which this class was designed), one rarely has to construct a `Response` directly.
444 +
445 +#### response.ok
446 +
447 +<small>*(spec-compliant)*</small>
448 +
449 +Convenience property representing if the request ended normally. Will evaluate to true if the response status was greater than or equal to 200 but smaller than 300.
450 +
451 +#### response.redirected
452 +
453 +<small>*(spec-compliant)*</small>
454 +
455 +Convenience property representing if the request has been redirected at least once. Will evaluate to true if the internal redirect counter is greater than 0.
456 +
457 +<a id="class-headers"></a>
458 +### Class: Headers
459 +
460 +This class allows manipulating and iterating over a set of HTTP headers. All methods specified in the [Fetch Standard][whatwg-fetch] are implemented.
461 +
462 +#### new Headers([init])
463 +
464 +<small>*(spec-compliant)*</small>
465 +
466 +- `init` Optional argument to pre-fill the `Headers` object
467 +
468 +Construct a new `Headers` object. `init` can be either `null`, a `Headers` object, an key-value map object or any iterable object.
469 +
470 +```js
471 +// Example adapted from https://fetch.spec.whatwg.org/#example-headers-class
472 +
473 +const meta = {
474 + 'Content-Type': 'text/xml',
475 + 'Breaking-Bad': '<3'
476 +};
477 +const headers = new Headers(meta);
478 +
479 +// The above is equivalent to
480 +const meta = [
481 + [ 'Content-Type', 'text/xml' ],
482 + [ 'Breaking-Bad', '<3' ]
483 +];
484 +const headers = new Headers(meta);
485 +
486 +// You can in fact use any iterable objects, like a Map or even another Headers
487 +const meta = new Map();
488 +meta.set('Content-Type', 'text/xml');
489 +meta.set('Breaking-Bad', '<3');
490 +const headers = new Headers(meta);
491 +const copyOfHeaders = new Headers(headers);
492 +```
493 +
494 +<a id="iface-body"></a>
495 +### Interface: Body
496 +
497 +`Body` is an abstract interface with methods that are applicable to both `Request` and `Response` classes.
498 +
499 +The following methods are not yet implemented in node-fetch at this moment:
500 +
501 +- `formData()`
502 +
503 +#### body.body
504 +
505 +<small>*(deviation from spec)*</small>
506 +
507 +* Node.js [`Readable` stream][node-readable]
508 +
509 +Data are encapsulated in the `Body` object. Note that while the [Fetch Standard][whatwg-fetch] requires the property to always be a WHATWG `ReadableStream`, in node-fetch it is a Node.js [`Readable` stream][node-readable].
510 +
511 +#### body.bodyUsed
512 +
513 +<small>*(spec-compliant)*</small>
514 +
515 +* `Boolean`
516 +
517 +A boolean property for if this body has been consumed. Per the specs, a consumed body cannot be used again.
518 +
519 +#### body.arrayBuffer()
520 +#### body.blob()
521 +#### body.json()
522 +#### body.text()
523 +
524 +<small>*(spec-compliant)*</small>
525 +
526 +* Returns: <code>Promise</code>
527 +
528 +Consume the body and return a promise that will resolve to one of these formats.
529 +
530 +#### body.buffer()
531 +
532 +<small>*(node-fetch extension)*</small>
533 +
534 +* Returns: <code>Promise&lt;Buffer&gt;</code>
535 +
536 +Consume the body and return a promise that will resolve to a Buffer.
537 +
538 +#### body.textConverted()
539 +
540 +<small>*(node-fetch extension)*</small>
541 +
542 +* Returns: <code>Promise&lt;String&gt;</code>
543 +
544 +Identical to `body.text()`, except instead of always converting to UTF-8, encoding sniffing will be performed and text converted to UTF-8 if possible.
545 +
546 +(This API requires an optional dependency of the npm package [encoding](https://www.npmjs.com/package/encoding), which you need to install manually. `webpack` users may see [a warning message](https://github.com/bitinn/node-fetch/issues/412#issuecomment-379007792) due to this optional dependency.)
547 +
548 +<a id="class-fetcherror"></a>
549 +### Class: FetchError
550 +
551 +<small>*(node-fetch extension)*</small>
552 +
553 +An operational error in the fetching process. See [ERROR-HANDLING.md][] for more info.
554 +
555 +<a id="class-aborterror"></a>
556 +### Class: AbortError
557 +
558 +<small>*(node-fetch extension)*</small>
559 +
560 +An Error thrown when the request is aborted in response to an `AbortSignal`'s `abort` event. It has a `name` property of `AbortError`. See [ERROR-HANDLING.MD][] for more info.
561 +
562 +## Acknowledgement
563 +
564 +Thanks to [github/fetch](https://github.com/github/fetch) for providing a solid implementation reference.
565 +
566 +`node-fetch` v1 was maintained by [@bitinn](https://github.com/bitinn); v2 was maintained by [@TimothyGu](https://github.com/timothygu), [@bitinn](https://github.com/bitinn) and [@jimmywarting](https://github.com/jimmywarting); v2 readme is written by [@jkantr](https://github.com/jkantr).
567 +
568 +## License
569 +
570 +MIT
571 +
572 +[npm-image]: https://flat.badgen.net/npm/v/node-fetch
573 +[npm-url]: https://www.npmjs.com/package/node-fetch
574 +[travis-image]: https://flat.badgen.net/travis/bitinn/node-fetch
575 +[travis-url]: https://travis-ci.org/bitinn/node-fetch
576 +[codecov-image]: https://flat.badgen.net/codecov/c/github/bitinn/node-fetch/master
577 +[codecov-url]: https://codecov.io/gh/bitinn/node-fetch
578 +[install-size-image]: https://flat.badgen.net/packagephobia/install/node-fetch
579 +[install-size-url]: https://packagephobia.now.sh/result?p=node-fetch
580 +[discord-image]: https://img.shields.io/discord/619915844268326952?color=%237289DA&label=Discord&style=flat-square
581 +[discord-url]: https://discord.gg/Zxbndcm
582 +[opencollective-image]: https://opencollective.com/node-fetch/backers.svg
583 +[opencollective-url]: https://opencollective.com/node-fetch
584 +[whatwg-fetch]: https://fetch.spec.whatwg.org/
585 +[response-init]: https://fetch.spec.whatwg.org/#responseinit
586 +[node-readable]: https://nodejs.org/api/stream.html#stream_readable_streams
587 +[mdn-headers]: https://developer.mozilla.org/en-US/docs/Web/API/Headers
588 +[LIMITS.md]: https://github.com/bitinn/node-fetch/blob/master/LIMITS.md
589 +[ERROR-HANDLING.md]: https://github.com/bitinn/node-fetch/blob/master/ERROR-HANDLING.md
590 +[UPGRADE-GUIDE.md]: https://github.com/bitinn/node-fetch/blob/master/UPGRADE-GUIDE.md
1 +"use strict";
2 +
3 +// ref: https://github.com/tc39/proposal-global
4 +var getGlobal = function () {
5 + // the only reliable means to get the global object is
6 + // `Function('return this')()`
7 + // However, this causes CSP violations in Chrome apps.
8 + if (typeof self !== 'undefined') { return self; }
9 + if (typeof window !== 'undefined') { return window; }
10 + if (typeof global !== 'undefined') { return global; }
11 + throw new Error('unable to locate global object');
12 +}
13 +
14 +var global = getGlobal();
15 +
16 +module.exports = exports = global.fetch;
17 +
18 +// Needed for TypeScript and Webpack.
19 +if (global.fetch) {
20 + exports.default = global.fetch.bind(global);
21 +}
22 +
23 +exports.Headers = global.Headers;
24 +exports.Request = global.Request;
25 +exports.Response = global.Response;
...\ No newline at end of file ...\ No newline at end of file
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 +const URL$1 = Url.URL || whatwgUrl.URL;
1405 +
1406 +// fix an issue where "PassThrough", "resolve" aren't a named export for node <10
1407 +const PassThrough$1 = Stream.PassThrough;
1408 +
1409 +const isDomainOrSubdomain = function isDomainOrSubdomain(destination, original) {
1410 + const orig = new URL$1(original).hostname;
1411 + const dest = new URL$1(destination).hostname;
1412 +
1413 + return orig === dest || orig[orig.length - dest.length - 1] === '.' && orig.endsWith(dest);
1414 +};
1415 +
1416 +/**
1417 + * Fetch function
1418 + *
1419 + * @param Mixed url Absolute url or Request instance
1420 + * @param Object opts Fetch options
1421 + * @return Promise
1422 + */
1423 +function fetch(url, opts) {
1424 +
1425 + // allow custom promise
1426 + if (!fetch.Promise) {
1427 + throw new Error('native promise missing, set fetch.Promise to your favorite alternative');
1428 + }
1429 +
1430 + Body.Promise = fetch.Promise;
1431 +
1432 + // wrap http.request into fetch
1433 + return new fetch.Promise(function (resolve, reject) {
1434 + // build request object
1435 + const request = new Request(url, opts);
1436 + const options = getNodeRequestOptions(request);
1437 +
1438 + const send = (options.protocol === 'https:' ? https : http).request;
1439 + const signal = request.signal;
1440 +
1441 + let response = null;
1442 +
1443 + const abort = function abort() {
1444 + let error = new AbortError('The user aborted a request.');
1445 + reject(error);
1446 + if (request.body && request.body instanceof Stream.Readable) {
1447 + request.body.destroy(error);
1448 + }
1449 + if (!response || !response.body) return;
1450 + response.body.emit('error', error);
1451 + };
1452 +
1453 + if (signal && signal.aborted) {
1454 + abort();
1455 + return;
1456 + }
1457 +
1458 + const abortAndFinalize = function abortAndFinalize() {
1459 + abort();
1460 + finalize();
1461 + };
1462 +
1463 + // send request
1464 + const req = send(options);
1465 + let reqTimeout;
1466 +
1467 + if (signal) {
1468 + signal.addEventListener('abort', abortAndFinalize);
1469 + }
1470 +
1471 + function finalize() {
1472 + req.abort();
1473 + if (signal) signal.removeEventListener('abort', abortAndFinalize);
1474 + clearTimeout(reqTimeout);
1475 + }
1476 +
1477 + if (request.timeout) {
1478 + req.once('socket', function (socket) {
1479 + reqTimeout = setTimeout(function () {
1480 + reject(new FetchError(`network timeout at: ${request.url}`, 'request-timeout'));
1481 + finalize();
1482 + }, request.timeout);
1483 + });
1484 + }
1485 +
1486 + req.on('error', function (err) {
1487 + reject(new FetchError(`request to ${request.url} failed, reason: ${err.message}`, 'system', err));
1488 + finalize();
1489 + });
1490 +
1491 + req.on('response', function (res) {
1492 + clearTimeout(reqTimeout);
1493 +
1494 + const headers = createHeadersLenient(res.headers);
1495 +
1496 + // HTTP fetch step 5
1497 + if (fetch.isRedirect(res.statusCode)) {
1498 + // HTTP fetch step 5.2
1499 + const location = headers.get('Location');
1500 +
1501 + // HTTP fetch step 5.3
1502 + let locationURL = null;
1503 + try {
1504 + locationURL = location === null ? null : new URL$1(location, request.url).toString();
1505 + } catch (err) {
1506 + // error here can only be invalid URL in Location: header
1507 + // do not throw when options.redirect == manual
1508 + // let the user extract the errorneous redirect URL
1509 + if (request.redirect !== 'manual') {
1510 + reject(new FetchError(`uri requested responds with an invalid redirect URL: ${location}`, 'invalid-redirect'));
1511 + finalize();
1512 + return;
1513 + }
1514 + }
1515 +
1516 + // HTTP fetch step 5.5
1517 + switch (request.redirect) {
1518 + case 'error':
1519 + reject(new FetchError(`uri requested responds with a redirect, redirect mode is set to error: ${request.url}`, 'no-redirect'));
1520 + finalize();
1521 + return;
1522 + case 'manual':
1523 + // node-fetch-specific step: make manual redirect a bit easier to use by setting the Location header value to the resolved URL.
1524 + if (locationURL !== null) {
1525 + // handle corrupted header
1526 + try {
1527 + headers.set('Location', locationURL);
1528 + } catch (err) {
1529 + // istanbul ignore next: nodejs server prevent invalid response headers, we can't test this through normal request
1530 + reject(err);
1531 + }
1532 + }
1533 + break;
1534 + case 'follow':
1535 + // HTTP-redirect fetch step 2
1536 + if (locationURL === null) {
1537 + break;
1538 + }
1539 +
1540 + // HTTP-redirect fetch step 5
1541 + if (request.counter >= request.follow) {
1542 + reject(new FetchError(`maximum redirect reached at: ${request.url}`, 'max-redirect'));
1543 + finalize();
1544 + return;
1545 + }
1546 +
1547 + // HTTP-redirect fetch step 6 (counter increment)
1548 + // Create a new Request object.
1549 + const requestOpts = {
1550 + headers: new Headers(request.headers),
1551 + follow: request.follow,
1552 + counter: request.counter + 1,
1553 + agent: request.agent,
1554 + compress: request.compress,
1555 + method: request.method,
1556 + body: request.body,
1557 + signal: request.signal,
1558 + timeout: request.timeout,
1559 + size: request.size
1560 + };
1561 +
1562 + if (!isDomainOrSubdomain(request.url, locationURL)) {
1563 + for (const name of ['authorization', 'www-authenticate', 'cookie', 'cookie2']) {
1564 + requestOpts.headers.delete(name);
1565 + }
1566 + }
1567 +
1568 + // HTTP-redirect fetch step 9
1569 + if (res.statusCode !== 303 && request.body && getTotalBytes(request) === null) {
1570 + reject(new FetchError('Cannot follow redirect with body being a readable stream', 'unsupported-redirect'));
1571 + finalize();
1572 + return;
1573 + }
1574 +
1575 + // HTTP-redirect fetch step 11
1576 + if (res.statusCode === 303 || (res.statusCode === 301 || res.statusCode === 302) && request.method === 'POST') {
1577 + requestOpts.method = 'GET';
1578 + requestOpts.body = undefined;
1579 + requestOpts.headers.delete('content-length');
1580 + }
1581 +
1582 + // HTTP-redirect fetch step 15
1583 + resolve(fetch(new Request(locationURL, requestOpts)));
1584 + finalize();
1585 + return;
1586 + }
1587 + }
1588 +
1589 + // prepare response
1590 + res.once('end', function () {
1591 + if (signal) signal.removeEventListener('abort', abortAndFinalize);
1592 + });
1593 + let body = res.pipe(new PassThrough$1());
1594 +
1595 + const response_options = {
1596 + url: request.url,
1597 + status: res.statusCode,
1598 + statusText: res.statusMessage,
1599 + headers: headers,
1600 + size: request.size,
1601 + timeout: request.timeout,
1602 + counter: request.counter
1603 + };
1604 +
1605 + // HTTP-network fetch step 12.1.1.3
1606 + const codings = headers.get('Content-Encoding');
1607 +
1608 + // HTTP-network fetch step 12.1.1.4: handle content codings
1609 +
1610 + // in following scenarios we ignore compression support
1611 + // 1. compression support is disabled
1612 + // 2. HEAD request
1613 + // 3. no Content-Encoding header
1614 + // 4. no content response (204)
1615 + // 5. content not modified response (304)
1616 + if (!request.compress || request.method === 'HEAD' || codings === null || res.statusCode === 204 || res.statusCode === 304) {
1617 + response = new Response(body, response_options);
1618 + resolve(response);
1619 + return;
1620 + }
1621 +
1622 + // For Node v6+
1623 + // Be less strict when decoding compressed responses, since sometimes
1624 + // servers send slightly invalid responses that are still accepted
1625 + // by common browsers.
1626 + // Always using Z_SYNC_FLUSH is what cURL does.
1627 + const zlibOptions = {
1628 + flush: zlib.Z_SYNC_FLUSH,
1629 + finishFlush: zlib.Z_SYNC_FLUSH
1630 + };
1631 +
1632 + // for gzip
1633 + if (codings == 'gzip' || codings == 'x-gzip') {
1634 + body = body.pipe(zlib.createGunzip(zlibOptions));
1635 + response = new Response(body, response_options);
1636 + resolve(response);
1637 + return;
1638 + }
1639 +
1640 + // for deflate
1641 + if (codings == 'deflate' || codings == 'x-deflate') {
1642 + // handle the infamous raw deflate response from old servers
1643 + // a hack for old IIS and Apache servers
1644 + const raw = res.pipe(new PassThrough$1());
1645 + raw.once('data', function (chunk) {
1646 + // see http://stackoverflow.com/questions/37519828
1647 + if ((chunk[0] & 0x0F) === 0x08) {
1648 + body = body.pipe(zlib.createInflate());
1649 + } else {
1650 + body = body.pipe(zlib.createInflateRaw());
1651 + }
1652 + response = new Response(body, response_options);
1653 + resolve(response);
1654 + });
1655 + return;
1656 + }
1657 +
1658 + // for br
1659 + if (codings == 'br' && typeof zlib.createBrotliDecompress === 'function') {
1660 + body = body.pipe(zlib.createBrotliDecompress());
1661 + response = new Response(body, response_options);
1662 + resolve(response);
1663 + return;
1664 + }
1665 +
1666 + // otherwise, use response as-is
1667 + response = new Response(body, response_options);
1668 + resolve(response);
1669 + });
1670 +
1671 + writeToStream(req, request);
1672 + });
1673 +}
1674 +/**
1675 + * Redirect code matching
1676 + *
1677 + * @param Number code Status code
1678 + * @return Boolean
1679 + */
1680 +fetch.isRedirect = function (code) {
1681 + return code === 301 || code === 302 || code === 303 || code === 307 || code === 308;
1682 +};
1683 +
1684 +// expose Promise
1685 +fetch.Promise = global.Promise;
1686 +
1687 +export default fetch;
1688 +export { Headers, Request, Response, FetchError };
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 whatwgUrl = _interopDefault(require('whatwg-url'));
11 +var https = _interopDefault(require('https'));
12 +var zlib = _interopDefault(require('zlib'));
13 +
14 +// Based on https://github.com/tmpvar/jsdom/blob/aa85b2abf07766ff7bf5c1f6daafb3726f2f2db5/lib/jsdom/living/blob.js
15 +
16 +// fix for "Readable" isn't a named export issue
17 +const Readable = Stream.Readable;
18 +
19 +const BUFFER = Symbol('buffer');
20 +const TYPE = Symbol('type');
21 +
22 +class Blob {
23 + constructor() {
24 + this[TYPE] = '';
25 +
26 + const blobParts = arguments[0];
27 + const options = arguments[1];
28 +
29 + const buffers = [];
30 + let size = 0;
31 +
32 + if (blobParts) {
33 + const a = blobParts;
34 + const length = Number(a.length);
35 + for (let i = 0; i < length; i++) {
36 + const element = a[i];
37 + let buffer;
38 + if (element instanceof Buffer) {
39 + buffer = element;
40 + } else if (ArrayBuffer.isView(element)) {
41 + buffer = Buffer.from(element.buffer, element.byteOffset, element.byteLength);
42 + } else if (element instanceof ArrayBuffer) {
43 + buffer = Buffer.from(element);
44 + } else if (element instanceof Blob) {
45 + buffer = element[BUFFER];
46 + } else {
47 + buffer = Buffer.from(typeof element === 'string' ? element : String(element));
48 + }
49 + size += buffer.length;
50 + buffers.push(buffer);
51 + }
52 + }
53 +
54 + this[BUFFER] = Buffer.concat(buffers);
55 +
56 + let type = options && options.type !== undefined && String(options.type).toLowerCase();
57 + if (type && !/[^\u0020-\u007E]/.test(type)) {
58 + this[TYPE] = type;
59 + }
60 + }
61 + get size() {
62 + return this[BUFFER].length;
63 + }
64 + get type() {
65 + return this[TYPE];
66 + }
67 + text() {
68 + return Promise.resolve(this[BUFFER].toString());
69 + }
70 + arrayBuffer() {
71 + const buf = this[BUFFER];
72 + const ab = buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
73 + return Promise.resolve(ab);
74 + }
75 + stream() {
76 + const readable = new Readable();
77 + readable._read = function () {};
78 + readable.push(this[BUFFER]);
79 + readable.push(null);
80 + return readable;
81 + }
82 + toString() {
83 + return '[object Blob]';
84 + }
85 + slice() {
86 + const size = this.size;
87 +
88 + const start = arguments[0];
89 + const end = arguments[1];
90 + let relativeStart, relativeEnd;
91 + if (start === undefined) {
92 + relativeStart = 0;
93 + } else if (start < 0) {
94 + relativeStart = Math.max(size + start, 0);
95 + } else {
96 + relativeStart = Math.min(start, size);
97 + }
98 + if (end === undefined) {
99 + relativeEnd = size;
100 + } else if (end < 0) {
101 + relativeEnd = Math.max(size + end, 0);
102 + } else {
103 + relativeEnd = Math.min(end, size);
104 + }
105 + const span = Math.max(relativeEnd - relativeStart, 0);
106 +
107 + const buffer = this[BUFFER];
108 + const slicedBuffer = buffer.slice(relativeStart, relativeStart + span);
109 + const blob = new Blob([], { type: arguments[2] });
110 + blob[BUFFER] = slicedBuffer;
111 + return blob;
112 + }
113 +}
114 +
115 +Object.defineProperties(Blob.prototype, {
116 + size: { enumerable: true },
117 + type: { enumerable: true },
118 + slice: { enumerable: true }
119 +});
120 +
121 +Object.defineProperty(Blob.prototype, Symbol.toStringTag, {
122 + value: 'Blob',
123 + writable: false,
124 + enumerable: false,
125 + configurable: true
126 +});
127 +
128 +/**
129 + * fetch-error.js
130 + *
131 + * FetchError interface for operational errors
132 + */
133 +
134 +/**
135 + * Create FetchError instance
136 + *
137 + * @param String message Error message for human
138 + * @param String type Error type for machine
139 + * @param String systemError For Node.js system error
140 + * @return FetchError
141 + */
142 +function FetchError(message, type, systemError) {
143 + Error.call(this, message);
144 +
145 + this.message = message;
146 + this.type = type;
147 +
148 + // when err.type is `system`, err.code contains system error code
149 + if (systemError) {
150 + this.code = this.errno = systemError.code;
151 + }
152 +
153 + // hide custom error implementation details from end-users
154 + Error.captureStackTrace(this, this.constructor);
155 +}
156 +
157 +FetchError.prototype = Object.create(Error.prototype);
158 +FetchError.prototype.constructor = FetchError;
159 +FetchError.prototype.name = 'FetchError';
160 +
161 +let convert;
162 +try {
163 + convert = require('encoding').convert;
164 +} catch (e) {}
165 +
166 +const INTERNALS = Symbol('Body internals');
167 +
168 +// fix an issue where "PassThrough" isn't a named export for node <10
169 +const PassThrough = Stream.PassThrough;
170 +
171 +/**
172 + * Body mixin
173 + *
174 + * Ref: https://fetch.spec.whatwg.org/#body
175 + *
176 + * @param Stream body Readable stream
177 + * @param Object opts Response options
178 + * @return Void
179 + */
180 +function Body(body) {
181 + var _this = this;
182 +
183 + var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
184 + _ref$size = _ref.size;
185 +
186 + let size = _ref$size === undefined ? 0 : _ref$size;
187 + var _ref$timeout = _ref.timeout;
188 + let timeout = _ref$timeout === undefined ? 0 : _ref$timeout;
189 +
190 + if (body == null) {
191 + // body is undefined or null
192 + body = null;
193 + } else if (isURLSearchParams(body)) {
194 + // body is a URLSearchParams
195 + body = Buffer.from(body.toString());
196 + } else if (isBlob(body)) ; else if (Buffer.isBuffer(body)) ; else if (Object.prototype.toString.call(body) === '[object ArrayBuffer]') {
197 + // body is ArrayBuffer
198 + body = Buffer.from(body);
199 + } else if (ArrayBuffer.isView(body)) {
200 + // body is ArrayBufferView
201 + body = Buffer.from(body.buffer, body.byteOffset, body.byteLength);
202 + } else if (body instanceof Stream) ; else {
203 + // none of the above
204 + // coerce to string then buffer
205 + body = Buffer.from(String(body));
206 + }
207 + this[INTERNALS] = {
208 + body,
209 + disturbed: false,
210 + error: null
211 + };
212 + this.size = size;
213 + this.timeout = timeout;
214 +
215 + if (body instanceof Stream) {
216 + body.on('error', function (err) {
217 + const error = err.name === 'AbortError' ? err : new FetchError(`Invalid response body while trying to fetch ${_this.url}: ${err.message}`, 'system', err);
218 + _this[INTERNALS].error = error;
219 + });
220 + }
221 +}
222 +
223 +Body.prototype = {
224 + get body() {
225 + return this[INTERNALS].body;
226 + },
227 +
228 + get bodyUsed() {
229 + return this[INTERNALS].disturbed;
230 + },
231 +
232 + /**
233 + * Decode response as ArrayBuffer
234 + *
235 + * @return Promise
236 + */
237 + arrayBuffer() {
238 + return consumeBody.call(this).then(function (buf) {
239 + return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
240 + });
241 + },
242 +
243 + /**
244 + * Return raw response as Blob
245 + *
246 + * @return Promise
247 + */
248 + blob() {
249 + let ct = this.headers && this.headers.get('content-type') || '';
250 + return consumeBody.call(this).then(function (buf) {
251 + return Object.assign(
252 + // Prevent copying
253 + new Blob([], {
254 + type: ct.toLowerCase()
255 + }), {
256 + [BUFFER]: buf
257 + });
258 + });
259 + },
260 +
261 + /**
262 + * Decode response as json
263 + *
264 + * @return Promise
265 + */
266 + json() {
267 + var _this2 = this;
268 +
269 + return consumeBody.call(this).then(function (buffer) {
270 + try {
271 + return JSON.parse(buffer.toString());
272 + } catch (err) {
273 + return Body.Promise.reject(new FetchError(`invalid json response body at ${_this2.url} reason: ${err.message}`, 'invalid-json'));
274 + }
275 + });
276 + },
277 +
278 + /**
279 + * Decode response as text
280 + *
281 + * @return Promise
282 + */
283 + text() {
284 + return consumeBody.call(this).then(function (buffer) {
285 + return buffer.toString();
286 + });
287 + },
288 +
289 + /**
290 + * Decode response as buffer (non-spec api)
291 + *
292 + * @return Promise
293 + */
294 + buffer() {
295 + return consumeBody.call(this);
296 + },
297 +
298 + /**
299 + * Decode response as text, while automatically detecting the encoding and
300 + * trying to decode to UTF-8 (non-spec api)
301 + *
302 + * @return Promise
303 + */
304 + textConverted() {
305 + var _this3 = this;
306 +
307 + return consumeBody.call(this).then(function (buffer) {
308 + return convertBody(buffer, _this3.headers);
309 + });
310 + }
311 +};
312 +
313 +// In browsers, all properties are enumerable.
314 +Object.defineProperties(Body.prototype, {
315 + body: { enumerable: true },
316 + bodyUsed: { enumerable: true },
317 + arrayBuffer: { enumerable: true },
318 + blob: { enumerable: true },
319 + json: { enumerable: true },
320 + text: { enumerable: true }
321 +});
322 +
323 +Body.mixIn = function (proto) {
324 + for (const name of Object.getOwnPropertyNames(Body.prototype)) {
325 + // istanbul ignore else: future proof
326 + if (!(name in proto)) {
327 + const desc = Object.getOwnPropertyDescriptor(Body.prototype, name);
328 + Object.defineProperty(proto, name, desc);
329 + }
330 + }
331 +};
332 +
333 +/**
334 + * Consume and convert an entire Body to a Buffer.
335 + *
336 + * Ref: https://fetch.spec.whatwg.org/#concept-body-consume-body
337 + *
338 + * @return Promise
339 + */
340 +function consumeBody() {
341 + var _this4 = this;
342 +
343 + if (this[INTERNALS].disturbed) {
344 + return Body.Promise.reject(new TypeError(`body used already for: ${this.url}`));
345 + }
346 +
347 + this[INTERNALS].disturbed = true;
348 +
349 + if (this[INTERNALS].error) {
350 + return Body.Promise.reject(this[INTERNALS].error);
351 + }
352 +
353 + let body = this.body;
354 +
355 + // body is null
356 + if (body === null) {
357 + return Body.Promise.resolve(Buffer.alloc(0));
358 + }
359 +
360 + // body is blob
361 + if (isBlob(body)) {
362 + body = body.stream();
363 + }
364 +
365 + // body is buffer
366 + if (Buffer.isBuffer(body)) {
367 + return Body.Promise.resolve(body);
368 + }
369 +
370 + // istanbul ignore if: should never happen
371 + if (!(body instanceof Stream)) {
372 + return Body.Promise.resolve(Buffer.alloc(0));
373 + }
374 +
375 + // body is stream
376 + // get ready to actually consume the body
377 + let accum = [];
378 + let accumBytes = 0;
379 + let abort = false;
380 +
381 + return new Body.Promise(function (resolve, reject) {
382 + let resTimeout;
383 +
384 + // allow timeout on slow response body
385 + if (_this4.timeout) {
386 + resTimeout = setTimeout(function () {
387 + abort = true;
388 + reject(new FetchError(`Response timeout while trying to fetch ${_this4.url} (over ${_this4.timeout}ms)`, 'body-timeout'));
389 + }, _this4.timeout);
390 + }
391 +
392 + // handle stream errors
393 + body.on('error', function (err) {
394 + if (err.name === 'AbortError') {
395 + // if the request was aborted, reject with this Error
396 + abort = true;
397 + reject(err);
398 + } else {
399 + // other errors, such as incorrect content-encoding
400 + reject(new FetchError(`Invalid response body while trying to fetch ${_this4.url}: ${err.message}`, 'system', err));
401 + }
402 + });
403 +
404 + body.on('data', function (chunk) {
405 + if (abort || chunk === null) {
406 + return;
407 + }
408 +
409 + if (_this4.size && accumBytes + chunk.length > _this4.size) {
410 + abort = true;
411 + reject(new FetchError(`content size at ${_this4.url} over limit: ${_this4.size}`, 'max-size'));
412 + return;
413 + }
414 +
415 + accumBytes += chunk.length;
416 + accum.push(chunk);
417 + });
418 +
419 + body.on('end', function () {
420 + if (abort) {
421 + return;
422 + }
423 +
424 + clearTimeout(resTimeout);
425 +
426 + try {
427 + resolve(Buffer.concat(accum, accumBytes));
428 + } catch (err) {
429 + // handle streams that have accumulated too much data (issue #414)
430 + reject(new FetchError(`Could not create Buffer from response body for ${_this4.url}: ${err.message}`, 'system', err));
431 + }
432 + });
433 + });
434 +}
435 +
436 +/**
437 + * Detect buffer encoding and convert to target encoding
438 + * ref: http://www.w3.org/TR/2011/WD-html5-20110113/parsing.html#determining-the-character-encoding
439 + *
440 + * @param Buffer buffer Incoming buffer
441 + * @param String encoding Target encoding
442 + * @return String
443 + */
444 +function convertBody(buffer, headers) {
445 + if (typeof convert !== 'function') {
446 + throw new Error('The package `encoding` must be installed to use the textConverted() function');
447 + }
448 +
449 + const ct = headers.get('content-type');
450 + let charset = 'utf-8';
451 + let res, str;
452 +
453 + // header
454 + if (ct) {
455 + res = /charset=([^;]*)/i.exec(ct);
456 + }
457 +
458 + // no charset in content type, peek at response body for at most 1024 bytes
459 + str = buffer.slice(0, 1024).toString();
460 +
461 + // html5
462 + if (!res && str) {
463 + res = /<meta.+?charset=(['"])(.+?)\1/i.exec(str);
464 + }
465 +
466 + // html4
467 + if (!res && str) {
468 + res = /<meta[\s]+?http-equiv=(['"])content-type\1[\s]+?content=(['"])(.+?)\2/i.exec(str);
469 + if (!res) {
470 + res = /<meta[\s]+?content=(['"])(.+?)\1[\s]+?http-equiv=(['"])content-type\3/i.exec(str);
471 + if (res) {
472 + res.pop(); // drop last quote
473 + }
474 + }
475 +
476 + if (res) {
477 + res = /charset=(.*)/i.exec(res.pop());
478 + }
479 + }
480 +
481 + // xml
482 + if (!res && str) {
483 + res = /<\?xml.+?encoding=(['"])(.+?)\1/i.exec(str);
484 + }
485 +
486 + // found charset
487 + if (res) {
488 + charset = res.pop();
489 +
490 + // prevent decode issues when sites use incorrect encoding
491 + // ref: https://hsivonen.fi/encoding-menu/
492 + if (charset === 'gb2312' || charset === 'gbk') {
493 + charset = 'gb18030';
494 + }
495 + }
496 +
497 + // turn raw buffers into a single utf-8 buffer
498 + return convert(buffer, 'UTF-8', charset).toString();
499 +}
500 +
501 +/**
502 + * Detect a URLSearchParams object
503 + * ref: https://github.com/bitinn/node-fetch/issues/296#issuecomment-307598143
504 + *
505 + * @param Object obj Object to detect by type or brand
506 + * @return String
507 + */
508 +function isURLSearchParams(obj) {
509 + // Duck-typing as a necessary condition.
510 + 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') {
511 + return false;
512 + }
513 +
514 + // Brand-checking and more duck-typing as optional condition.
515 + return obj.constructor.name === 'URLSearchParams' || Object.prototype.toString.call(obj) === '[object URLSearchParams]' || typeof obj.sort === 'function';
516 +}
517 +
518 +/**
519 + * Check if `obj` is a W3C `Blob` object (which `File` inherits from)
520 + * @param {*} obj
521 + * @return {boolean}
522 + */
523 +function isBlob(obj) {
524 + 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]);
525 +}
526 +
527 +/**
528 + * Clone body given Res/Req instance
529 + *
530 + * @param Mixed instance Response or Request instance
531 + * @return Mixed
532 + */
533 +function clone(instance) {
534 + let p1, p2;
535 + let body = instance.body;
536 +
537 + // don't allow cloning a used body
538 + if (instance.bodyUsed) {
539 + throw new Error('cannot clone body after it is used');
540 + }
541 +
542 + // check that body is a stream and not form-data object
543 + // note: we can't clone the form-data object without having it as a dependency
544 + if (body instanceof Stream && typeof body.getBoundary !== 'function') {
545 + // tee instance body
546 + p1 = new PassThrough();
547 + p2 = new PassThrough();
548 + body.pipe(p1);
549 + body.pipe(p2);
550 + // set instance body to teed body and return the other teed body
551 + instance[INTERNALS].body = p1;
552 + body = p2;
553 + }
554 +
555 + return body;
556 +}
557 +
558 +/**
559 + * Performs the operation "extract a `Content-Type` value from |object|" as
560 + * specified in the specification:
561 + * https://fetch.spec.whatwg.org/#concept-bodyinit-extract
562 + *
563 + * This function assumes that instance.body is present.
564 + *
565 + * @param Mixed instance Any options.body input
566 + */
567 +function extractContentType(body) {
568 + if (body === null) {
569 + // body is null
570 + return null;
571 + } else if (typeof body === 'string') {
572 + // body is string
573 + return 'text/plain;charset=UTF-8';
574 + } else if (isURLSearchParams(body)) {
575 + // body is a URLSearchParams
576 + return 'application/x-www-form-urlencoded;charset=UTF-8';
577 + } else if (isBlob(body)) {
578 + // body is blob
579 + return body.type || null;
580 + } else if (Buffer.isBuffer(body)) {
581 + // body is buffer
582 + return null;
583 + } else if (Object.prototype.toString.call(body) === '[object ArrayBuffer]') {
584 + // body is ArrayBuffer
585 + return null;
586 + } else if (ArrayBuffer.isView(body)) {
587 + // body is ArrayBufferView
588 + return null;
589 + } else if (typeof body.getBoundary === 'function') {
590 + // detect form data input from form-data module
591 + return `multipart/form-data;boundary=${body.getBoundary()}`;
592 + } else if (body instanceof Stream) {
593 + // body is stream
594 + // can't really do much about this
595 + return null;
596 + } else {
597 + // Body constructor defaults other things to string
598 + return 'text/plain;charset=UTF-8';
599 + }
600 +}
601 +
602 +/**
603 + * The Fetch Standard treats this as if "total bytes" is a property on the body.
604 + * For us, we have to explicitly get it with a function.
605 + *
606 + * ref: https://fetch.spec.whatwg.org/#concept-body-total-bytes
607 + *
608 + * @param Body instance Instance of Body
609 + * @return Number? Number of bytes, or null if not possible
610 + */
611 +function getTotalBytes(instance) {
612 + const body = instance.body;
613 +
614 +
615 + if (body === null) {
616 + // body is null
617 + return 0;
618 + } else if (isBlob(body)) {
619 + return body.size;
620 + } else if (Buffer.isBuffer(body)) {
621 + // body is buffer
622 + return body.length;
623 + } else if (body && typeof body.getLengthSync === 'function') {
624 + // detect form data input from form-data module
625 + if (body._lengthRetrievers && body._lengthRetrievers.length == 0 || // 1.x
626 + body.hasKnownLength && body.hasKnownLength()) {
627 + // 2.x
628 + return body.getLengthSync();
629 + }
630 + return null;
631 + } else {
632 + // body is stream
633 + return null;
634 + }
635 +}
636 +
637 +/**
638 + * Write a Body to a Node.js WritableStream (e.g. http.Request) object.
639 + *
640 + * @param Body instance Instance of Body
641 + * @return Void
642 + */
643 +function writeToStream(dest, instance) {
644 + const body = instance.body;
645 +
646 +
647 + if (body === null) {
648 + // body is null
649 + dest.end();
650 + } else if (isBlob(body)) {
651 + body.stream().pipe(dest);
652 + } else if (Buffer.isBuffer(body)) {
653 + // body is buffer
654 + dest.write(body);
655 + dest.end();
656 + } else {
657 + // body is stream
658 + body.pipe(dest);
659 + }
660 +}
661 +
662 +// expose Promise
663 +Body.Promise = global.Promise;
664 +
665 +/**
666 + * headers.js
667 + *
668 + * Headers class offers convenient helpers
669 + */
670 +
671 +const invalidTokenRegex = /[^\^_`a-zA-Z\-0-9!#$%&'*+.|~]/;
672 +const invalidHeaderCharRegex = /[^\t\x20-\x7e\x80-\xff]/;
673 +
674 +function validateName(name) {
675 + name = `${name}`;
676 + if (invalidTokenRegex.test(name) || name === '') {
677 + throw new TypeError(`${name} is not a legal HTTP header name`);
678 + }
679 +}
680 +
681 +function validateValue(value) {
682 + value = `${value}`;
683 + if (invalidHeaderCharRegex.test(value)) {
684 + throw new TypeError(`${value} is not a legal HTTP header value`);
685 + }
686 +}
687 +
688 +/**
689 + * Find the key in the map object given a header name.
690 + *
691 + * Returns undefined if not found.
692 + *
693 + * @param String name Header name
694 + * @return String|Undefined
695 + */
696 +function find(map, name) {
697 + name = name.toLowerCase();
698 + for (const key in map) {
699 + if (key.toLowerCase() === name) {
700 + return key;
701 + }
702 + }
703 + return undefined;
704 +}
705 +
706 +const MAP = Symbol('map');
707 +class Headers {
708 + /**
709 + * Headers class
710 + *
711 + * @param Object headers Response headers
712 + * @return Void
713 + */
714 + constructor() {
715 + let init = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : undefined;
716 +
717 + this[MAP] = Object.create(null);
718 +
719 + if (init instanceof Headers) {
720 + const rawHeaders = init.raw();
721 + const headerNames = Object.keys(rawHeaders);
722 +
723 + for (const headerName of headerNames) {
724 + for (const value of rawHeaders[headerName]) {
725 + this.append(headerName, value);
726 + }
727 + }
728 +
729 + return;
730 + }
731 +
732 + // We don't worry about converting prop to ByteString here as append()
733 + // will handle it.
734 + if (init == null) ; else if (typeof init === 'object') {
735 + const method = init[Symbol.iterator];
736 + if (method != null) {
737 + if (typeof method !== 'function') {
738 + throw new TypeError('Header pairs must be iterable');
739 + }
740 +
741 + // sequence<sequence<ByteString>>
742 + // Note: per spec we have to first exhaust the lists then process them
743 + const pairs = [];
744 + for (const pair of init) {
745 + if (typeof pair !== 'object' || typeof pair[Symbol.iterator] !== 'function') {
746 + throw new TypeError('Each header pair must be iterable');
747 + }
748 + pairs.push(Array.from(pair));
749 + }
750 +
751 + for (const pair of pairs) {
752 + if (pair.length !== 2) {
753 + throw new TypeError('Each header pair must be a name/value tuple');
754 + }
755 + this.append(pair[0], pair[1]);
756 + }
757 + } else {
758 + // record<ByteString, ByteString>
759 + for (const key of Object.keys(init)) {
760 + const value = init[key];
761 + this.append(key, value);
762 + }
763 + }
764 + } else {
765 + throw new TypeError('Provided initializer must be an object');
766 + }
767 + }
768 +
769 + /**
770 + * Return combined header value given name
771 + *
772 + * @param String name Header name
773 + * @return Mixed
774 + */
775 + get(name) {
776 + name = `${name}`;
777 + validateName(name);
778 + const key = find(this[MAP], name);
779 + if (key === undefined) {
780 + return null;
781 + }
782 +
783 + return this[MAP][key].join(', ');
784 + }
785 +
786 + /**
787 + * Iterate over all headers
788 + *
789 + * @param Function callback Executed for each item with parameters (value, name, thisArg)
790 + * @param Boolean thisArg `this` context for callback function
791 + * @return Void
792 + */
793 + forEach(callback) {
794 + let thisArg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined;
795 +
796 + let pairs = getHeaders(this);
797 + let i = 0;
798 + while (i < pairs.length) {
799 + var _pairs$i = pairs[i];
800 + const name = _pairs$i[0],
801 + value = _pairs$i[1];
802 +
803 + callback.call(thisArg, value, name, this);
804 + pairs = getHeaders(this);
805 + i++;
806 + }
807 + }
808 +
809 + /**
810 + * Overwrite header values given name
811 + *
812 + * @param String name Header name
813 + * @param String value Header value
814 + * @return Void
815 + */
816 + set(name, value) {
817 + name = `${name}`;
818 + value = `${value}`;
819 + validateName(name);
820 + validateValue(value);
821 + const key = find(this[MAP], name);
822 + this[MAP][key !== undefined ? key : name] = [value];
823 + }
824 +
825 + /**
826 + * Append a value onto existing header
827 + *
828 + * @param String name Header name
829 + * @param String value Header value
830 + * @return Void
831 + */
832 + append(name, value) {
833 + name = `${name}`;
834 + value = `${value}`;
835 + validateName(name);
836 + validateValue(value);
837 + const key = find(this[MAP], name);
838 + if (key !== undefined) {
839 + this[MAP][key].push(value);
840 + } else {
841 + this[MAP][name] = [value];
842 + }
843 + }
844 +
845 + /**
846 + * Check for header name existence
847 + *
848 + * @param String name Header name
849 + * @return Boolean
850 + */
851 + has(name) {
852 + name = `${name}`;
853 + validateName(name);
854 + return find(this[MAP], name) !== undefined;
855 + }
856 +
857 + /**
858 + * Delete all header values given name
859 + *
860 + * @param String name Header name
861 + * @return Void
862 + */
863 + delete(name) {
864 + name = `${name}`;
865 + validateName(name);
866 + const key = find(this[MAP], name);
867 + if (key !== undefined) {
868 + delete this[MAP][key];
869 + }
870 + }
871 +
872 + /**
873 + * Return raw headers (non-spec api)
874 + *
875 + * @return Object
876 + */
877 + raw() {
878 + return this[MAP];
879 + }
880 +
881 + /**
882 + * Get an iterator on keys.
883 + *
884 + * @return Iterator
885 + */
886 + keys() {
887 + return createHeadersIterator(this, 'key');
888 + }
889 +
890 + /**
891 + * Get an iterator on values.
892 + *
893 + * @return Iterator
894 + */
895 + values() {
896 + return createHeadersIterator(this, 'value');
897 + }
898 +
899 + /**
900 + * Get an iterator on entries.
901 + *
902 + * This is the default iterator of the Headers object.
903 + *
904 + * @return Iterator
905 + */
906 + [Symbol.iterator]() {
907 + return createHeadersIterator(this, 'key+value');
908 + }
909 +}
910 +Headers.prototype.entries = Headers.prototype[Symbol.iterator];
911 +
912 +Object.defineProperty(Headers.prototype, Symbol.toStringTag, {
913 + value: 'Headers',
914 + writable: false,
915 + enumerable: false,
916 + configurable: true
917 +});
918 +
919 +Object.defineProperties(Headers.prototype, {
920 + get: { enumerable: true },
921 + forEach: { enumerable: true },
922 + set: { enumerable: true },
923 + append: { enumerable: true },
924 + has: { enumerable: true },
925 + delete: { enumerable: true },
926 + keys: { enumerable: true },
927 + values: { enumerable: true },
928 + entries: { enumerable: true }
929 +});
930 +
931 +function getHeaders(headers) {
932 + let kind = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'key+value';
933 +
934 + const keys = Object.keys(headers[MAP]).sort();
935 + return keys.map(kind === 'key' ? function (k) {
936 + return k.toLowerCase();
937 + } : kind === 'value' ? function (k) {
938 + return headers[MAP][k].join(', ');
939 + } : function (k) {
940 + return [k.toLowerCase(), headers[MAP][k].join(', ')];
941 + });
942 +}
943 +
944 +const INTERNAL = Symbol('internal');
945 +
946 +function createHeadersIterator(target, kind) {
947 + const iterator = Object.create(HeadersIteratorPrototype);
948 + iterator[INTERNAL] = {
949 + target,
950 + kind,
951 + index: 0
952 + };
953 + return iterator;
954 +}
955 +
956 +const HeadersIteratorPrototype = Object.setPrototypeOf({
957 + next() {
958 + // istanbul ignore if
959 + if (!this || Object.getPrototypeOf(this) !== HeadersIteratorPrototype) {
960 + throw new TypeError('Value of `this` is not a HeadersIterator');
961 + }
962 +
963 + var _INTERNAL = this[INTERNAL];
964 + const target = _INTERNAL.target,
965 + kind = _INTERNAL.kind,
966 + index = _INTERNAL.index;
967 +
968 + const values = getHeaders(target, kind);
969 + const len = values.length;
970 + if (index >= len) {
971 + return {
972 + value: undefined,
973 + done: true
974 + };
975 + }
976 +
977 + this[INTERNAL].index = index + 1;
978 +
979 + return {
980 + value: values[index],
981 + done: false
982 + };
983 + }
984 +}, Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]())));
985 +
986 +Object.defineProperty(HeadersIteratorPrototype, Symbol.toStringTag, {
987 + value: 'HeadersIterator',
988 + writable: false,
989 + enumerable: false,
990 + configurable: true
991 +});
992 +
993 +/**
994 + * Export the Headers object in a form that Node.js can consume.
995 + *
996 + * @param Headers headers
997 + * @return Object
998 + */
999 +function exportNodeCompatibleHeaders(headers) {
1000 + const obj = Object.assign({ __proto__: null }, headers[MAP]);
1001 +
1002 + // http.request() only supports string as Host header. This hack makes
1003 + // specifying custom Host header possible.
1004 + const hostHeaderKey = find(headers[MAP], 'Host');
1005 + if (hostHeaderKey !== undefined) {
1006 + obj[hostHeaderKey] = obj[hostHeaderKey][0];
1007 + }
1008 +
1009 + return obj;
1010 +}
1011 +
1012 +/**
1013 + * Create a Headers object from an object of headers, ignoring those that do
1014 + * not conform to HTTP grammar productions.
1015 + *
1016 + * @param Object obj Object of headers
1017 + * @return Headers
1018 + */
1019 +function createHeadersLenient(obj) {
1020 + const headers = new Headers();
1021 + for (const name of Object.keys(obj)) {
1022 + if (invalidTokenRegex.test(name)) {
1023 + continue;
1024 + }
1025 + if (Array.isArray(obj[name])) {
1026 + for (const val of obj[name]) {
1027 + if (invalidHeaderCharRegex.test(val)) {
1028 + continue;
1029 + }
1030 + if (headers[MAP][name] === undefined) {
1031 + headers[MAP][name] = [val];
1032 + } else {
1033 + headers[MAP][name].push(val);
1034 + }
1035 + }
1036 + } else if (!invalidHeaderCharRegex.test(obj[name])) {
1037 + headers[MAP][name] = [obj[name]];
1038 + }
1039 + }
1040 + return headers;
1041 +}
1042 +
1043 +const INTERNALS$1 = Symbol('Response internals');
1044 +
1045 +// fix an issue where "STATUS_CODES" aren't a named export for node <10
1046 +const STATUS_CODES = http.STATUS_CODES;
1047 +
1048 +/**
1049 + * Response class
1050 + *
1051 + * @param Stream body Readable stream
1052 + * @param Object opts Response options
1053 + * @return Void
1054 + */
1055 +class Response {
1056 + constructor() {
1057 + let body = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
1058 + let opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1059 +
1060 + Body.call(this, body, opts);
1061 +
1062 + const status = opts.status || 200;
1063 + const headers = new Headers(opts.headers);
1064 +
1065 + if (body != null && !headers.has('Content-Type')) {
1066 + const contentType = extractContentType(body);
1067 + if (contentType) {
1068 + headers.append('Content-Type', contentType);
1069 + }
1070 + }
1071 +
1072 + this[INTERNALS$1] = {
1073 + url: opts.url,
1074 + status,
1075 + statusText: opts.statusText || STATUS_CODES[status],
1076 + headers,
1077 + counter: opts.counter
1078 + };
1079 + }
1080 +
1081 + get url() {
1082 + return this[INTERNALS$1].url || '';
1083 + }
1084 +
1085 + get status() {
1086 + return this[INTERNALS$1].status;
1087 + }
1088 +
1089 + /**
1090 + * Convenience property representing if the request ended normally
1091 + */
1092 + get ok() {
1093 + return this[INTERNALS$1].status >= 200 && this[INTERNALS$1].status < 300;
1094 + }
1095 +
1096 + get redirected() {
1097 + return this[INTERNALS$1].counter > 0;
1098 + }
1099 +
1100 + get statusText() {
1101 + return this[INTERNALS$1].statusText;
1102 + }
1103 +
1104 + get headers() {
1105 + return this[INTERNALS$1].headers;
1106 + }
1107 +
1108 + /**
1109 + * Clone this response
1110 + *
1111 + * @return Response
1112 + */
1113 + clone() {
1114 + return new Response(clone(this), {
1115 + url: this.url,
1116 + status: this.status,
1117 + statusText: this.statusText,
1118 + headers: this.headers,
1119 + ok: this.ok,
1120 + redirected: this.redirected
1121 + });
1122 + }
1123 +}
1124 +
1125 +Body.mixIn(Response.prototype);
1126 +
1127 +Object.defineProperties(Response.prototype, {
1128 + url: { enumerable: true },
1129 + status: { enumerable: true },
1130 + ok: { enumerable: true },
1131 + redirected: { enumerable: true },
1132 + statusText: { enumerable: true },
1133 + headers: { enumerable: true },
1134 + clone: { enumerable: true }
1135 +});
1136 +
1137 +Object.defineProperty(Response.prototype, Symbol.toStringTag, {
1138 + value: 'Response',
1139 + writable: false,
1140 + enumerable: false,
1141 + configurable: true
1142 +});
1143 +
1144 +const INTERNALS$2 = Symbol('Request internals');
1145 +const URL = Url.URL || whatwgUrl.URL;
1146 +
1147 +// fix an issue where "format", "parse" aren't a named export for node <10
1148 +const parse_url = Url.parse;
1149 +const format_url = Url.format;
1150 +
1151 +/**
1152 + * Wrapper around `new URL` to handle arbitrary URLs
1153 + *
1154 + * @param {string} urlStr
1155 + * @return {void}
1156 + */
1157 +function parseURL(urlStr) {
1158 + /*
1159 + Check whether the URL is absolute or not
1160 + Scheme: https://tools.ietf.org/html/rfc3986#section-3.1
1161 + Absolute URL: https://tools.ietf.org/html/rfc3986#section-4.3
1162 + */
1163 + if (/^[a-zA-Z][a-zA-Z\d+\-.]*:/.exec(urlStr)) {
1164 + urlStr = new URL(urlStr).toString();
1165 + }
1166 +
1167 + // Fallback to old implementation for arbitrary URLs
1168 + return parse_url(urlStr);
1169 +}
1170 +
1171 +const streamDestructionSupported = 'destroy' in Stream.Readable.prototype;
1172 +
1173 +/**
1174 + * Check if a value is an instance of Request.
1175 + *
1176 + * @param Mixed input
1177 + * @return Boolean
1178 + */
1179 +function isRequest(input) {
1180 + return typeof input === 'object' && typeof input[INTERNALS$2] === 'object';
1181 +}
1182 +
1183 +function isAbortSignal(signal) {
1184 + const proto = signal && typeof signal === 'object' && Object.getPrototypeOf(signal);
1185 + return !!(proto && proto.constructor.name === 'AbortSignal');
1186 +}
1187 +
1188 +/**
1189 + * Request class
1190 + *
1191 + * @param Mixed input Url or Request instance
1192 + * @param Object init Custom options
1193 + * @return Void
1194 + */
1195 +class Request {
1196 + constructor(input) {
1197 + let init = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1198 +
1199 + let parsedURL;
1200 +
1201 + // normalize input
1202 + if (!isRequest(input)) {
1203 + if (input && input.href) {
1204 + // in order to support Node.js' Url objects; though WHATWG's URL objects
1205 + // will fall into this branch also (since their `toString()` will return
1206 + // `href` property anyway)
1207 + parsedURL = parseURL(input.href);
1208 + } else {
1209 + // coerce input to a string before attempting to parse
1210 + parsedURL = parseURL(`${input}`);
1211 + }
1212 + input = {};
1213 + } else {
1214 + parsedURL = parseURL(input.url);
1215 + }
1216 +
1217 + let method = init.method || input.method || 'GET';
1218 + method = method.toUpperCase();
1219 +
1220 + if ((init.body != null || isRequest(input) && input.body !== null) && (method === 'GET' || method === 'HEAD')) {
1221 + throw new TypeError('Request with GET/HEAD method cannot have body');
1222 + }
1223 +
1224 + let inputBody = init.body != null ? init.body : isRequest(input) && input.body !== null ? clone(input) : null;
1225 +
1226 + Body.call(this, inputBody, {
1227 + timeout: init.timeout || input.timeout || 0,
1228 + size: init.size || input.size || 0
1229 + });
1230 +
1231 + const headers = new Headers(init.headers || input.headers || {});
1232 +
1233 + if (inputBody != null && !headers.has('Content-Type')) {
1234 + const contentType = extractContentType(inputBody);
1235 + if (contentType) {
1236 + headers.append('Content-Type', contentType);
1237 + }
1238 + }
1239 +
1240 + let signal = isRequest(input) ? input.signal : null;
1241 + if ('signal' in init) signal = init.signal;
1242 +
1243 + if (signal != null && !isAbortSignal(signal)) {
1244 + throw new TypeError('Expected signal to be an instanceof AbortSignal');
1245 + }
1246 +
1247 + this[INTERNALS$2] = {
1248 + method,
1249 + redirect: init.redirect || input.redirect || 'follow',
1250 + headers,
1251 + parsedURL,
1252 + signal
1253 + };
1254 +
1255 + // node-fetch-only options
1256 + this.follow = init.follow !== undefined ? init.follow : input.follow !== undefined ? input.follow : 20;
1257 + this.compress = init.compress !== undefined ? init.compress : input.compress !== undefined ? input.compress : true;
1258 + this.counter = init.counter || input.counter || 0;
1259 + this.agent = init.agent || input.agent;
1260 + }
1261 +
1262 + get method() {
1263 + return this[INTERNALS$2].method;
1264 + }
1265 +
1266 + get url() {
1267 + return format_url(this[INTERNALS$2].parsedURL);
1268 + }
1269 +
1270 + get headers() {
1271 + return this[INTERNALS$2].headers;
1272 + }
1273 +
1274 + get redirect() {
1275 + return this[INTERNALS$2].redirect;
1276 + }
1277 +
1278 + get signal() {
1279 + return this[INTERNALS$2].signal;
1280 + }
1281 +
1282 + /**
1283 + * Clone this request
1284 + *
1285 + * @return Request
1286 + */
1287 + clone() {
1288 + return new Request(this);
1289 + }
1290 +}
1291 +
1292 +Body.mixIn(Request.prototype);
1293 +
1294 +Object.defineProperty(Request.prototype, Symbol.toStringTag, {
1295 + value: 'Request',
1296 + writable: false,
1297 + enumerable: false,
1298 + configurable: true
1299 +});
1300 +
1301 +Object.defineProperties(Request.prototype, {
1302 + method: { enumerable: true },
1303 + url: { enumerable: true },
1304 + headers: { enumerable: true },
1305 + redirect: { enumerable: true },
1306 + clone: { enumerable: true },
1307 + signal: { enumerable: true }
1308 +});
1309 +
1310 +/**
1311 + * Convert a Request to Node.js http request options.
1312 + *
1313 + * @param Request A Request instance
1314 + * @return Object The options object to be passed to http.request
1315 + */
1316 +function getNodeRequestOptions(request) {
1317 + const parsedURL = request[INTERNALS$2].parsedURL;
1318 + const headers = new Headers(request[INTERNALS$2].headers);
1319 +
1320 + // fetch step 1.3
1321 + if (!headers.has('Accept')) {
1322 + headers.set('Accept', '*/*');
1323 + }
1324 +
1325 + // Basic fetch
1326 + if (!parsedURL.protocol || !parsedURL.hostname) {
1327 + throw new TypeError('Only absolute URLs are supported');
1328 + }
1329 +
1330 + if (!/^https?:$/.test(parsedURL.protocol)) {
1331 + throw new TypeError('Only HTTP(S) protocols are supported');
1332 + }
1333 +
1334 + if (request.signal && request.body instanceof Stream.Readable && !streamDestructionSupported) {
1335 + throw new Error('Cancellation of streamed requests with AbortSignal is not supported in node < 8');
1336 + }
1337 +
1338 + // HTTP-network-or-cache fetch steps 2.4-2.7
1339 + let contentLengthValue = null;
1340 + if (request.body == null && /^(POST|PUT)$/i.test(request.method)) {
1341 + contentLengthValue = '0';
1342 + }
1343 + if (request.body != null) {
1344 + const totalBytes = getTotalBytes(request);
1345 + if (typeof totalBytes === 'number') {
1346 + contentLengthValue = String(totalBytes);
1347 + }
1348 + }
1349 + if (contentLengthValue) {
1350 + headers.set('Content-Length', contentLengthValue);
1351 + }
1352 +
1353 + // HTTP-network-or-cache fetch step 2.11
1354 + if (!headers.has('User-Agent')) {
1355 + headers.set('User-Agent', 'node-fetch/1.0 (+https://github.com/bitinn/node-fetch)');
1356 + }
1357 +
1358 + // HTTP-network-or-cache fetch step 2.15
1359 + if (request.compress && !headers.has('Accept-Encoding')) {
1360 + headers.set('Accept-Encoding', 'gzip,deflate');
1361 + }
1362 +
1363 + let agent = request.agent;
1364 + if (typeof agent === 'function') {
1365 + agent = agent(parsedURL);
1366 + }
1367 +
1368 + if (!headers.has('Connection') && !agent) {
1369 + headers.set('Connection', 'close');
1370 + }
1371 +
1372 + // HTTP-network fetch step 4.2
1373 + // chunked encoding is handled by Node.js
1374 +
1375 + return Object.assign({}, parsedURL, {
1376 + method: request.method,
1377 + headers: exportNodeCompatibleHeaders(headers),
1378 + agent
1379 + });
1380 +}
1381 +
1382 +/**
1383 + * abort-error.js
1384 + *
1385 + * AbortError interface for cancelled requests
1386 + */
1387 +
1388 +/**
1389 + * Create AbortError instance
1390 + *
1391 + * @param String message Error message for human
1392 + * @return AbortError
1393 + */
1394 +function AbortError(message) {
1395 + Error.call(this, message);
1396 +
1397 + this.type = 'aborted';
1398 + this.message = message;
1399 +
1400 + // hide custom error implementation details from end-users
1401 + Error.captureStackTrace(this, this.constructor);
1402 +}
1403 +
1404 +AbortError.prototype = Object.create(Error.prototype);
1405 +AbortError.prototype.constructor = AbortError;
1406 +AbortError.prototype.name = 'AbortError';
1407 +
1408 +const URL$1 = Url.URL || whatwgUrl.URL;
1409 +
1410 +// fix an issue where "PassThrough", "resolve" aren't a named export for node <10
1411 +const PassThrough$1 = Stream.PassThrough;
1412 +
1413 +const isDomainOrSubdomain = function isDomainOrSubdomain(destination, original) {
1414 + const orig = new URL$1(original).hostname;
1415 + const dest = new URL$1(destination).hostname;
1416 +
1417 + return orig === dest || orig[orig.length - dest.length - 1] === '.' && orig.endsWith(dest);
1418 +};
1419 +
1420 +/**
1421 + * Fetch function
1422 + *
1423 + * @param Mixed url Absolute url or Request instance
1424 + * @param Object opts Fetch options
1425 + * @return Promise
1426 + */
1427 +function fetch(url, opts) {
1428 +
1429 + // allow custom promise
1430 + if (!fetch.Promise) {
1431 + throw new Error('native promise missing, set fetch.Promise to your favorite alternative');
1432 + }
1433 +
1434 + Body.Promise = fetch.Promise;
1435 +
1436 + // wrap http.request into fetch
1437 + return new fetch.Promise(function (resolve, reject) {
1438 + // build request object
1439 + const request = new Request(url, opts);
1440 + const options = getNodeRequestOptions(request);
1441 +
1442 + const send = (options.protocol === 'https:' ? https : http).request;
1443 + const signal = request.signal;
1444 +
1445 + let response = null;
1446 +
1447 + const abort = function abort() {
1448 + let error = new AbortError('The user aborted a request.');
1449 + reject(error);
1450 + if (request.body && request.body instanceof Stream.Readable) {
1451 + request.body.destroy(error);
1452 + }
1453 + if (!response || !response.body) return;
1454 + response.body.emit('error', error);
1455 + };
1456 +
1457 + if (signal && signal.aborted) {
1458 + abort();
1459 + return;
1460 + }
1461 +
1462 + const abortAndFinalize = function abortAndFinalize() {
1463 + abort();
1464 + finalize();
1465 + };
1466 +
1467 + // send request
1468 + const req = send(options);
1469 + let reqTimeout;
1470 +
1471 + if (signal) {
1472 + signal.addEventListener('abort', abortAndFinalize);
1473 + }
1474 +
1475 + function finalize() {
1476 + req.abort();
1477 + if (signal) signal.removeEventListener('abort', abortAndFinalize);
1478 + clearTimeout(reqTimeout);
1479 + }
1480 +
1481 + if (request.timeout) {
1482 + req.once('socket', function (socket) {
1483 + reqTimeout = setTimeout(function () {
1484 + reject(new FetchError(`network timeout at: ${request.url}`, 'request-timeout'));
1485 + finalize();
1486 + }, request.timeout);
1487 + });
1488 + }
1489 +
1490 + req.on('error', function (err) {
1491 + reject(new FetchError(`request to ${request.url} failed, reason: ${err.message}`, 'system', err));
1492 + finalize();
1493 + });
1494 +
1495 + req.on('response', function (res) {
1496 + clearTimeout(reqTimeout);
1497 +
1498 + const headers = createHeadersLenient(res.headers);
1499 +
1500 + // HTTP fetch step 5
1501 + if (fetch.isRedirect(res.statusCode)) {
1502 + // HTTP fetch step 5.2
1503 + const location = headers.get('Location');
1504 +
1505 + // HTTP fetch step 5.3
1506 + let locationURL = null;
1507 + try {
1508 + locationURL = location === null ? null : new URL$1(location, request.url).toString();
1509 + } catch (err) {
1510 + // error here can only be invalid URL in Location: header
1511 + // do not throw when options.redirect == manual
1512 + // let the user extract the errorneous redirect URL
1513 + if (request.redirect !== 'manual') {
1514 + reject(new FetchError(`uri requested responds with an invalid redirect URL: ${location}`, 'invalid-redirect'));
1515 + finalize();
1516 + return;
1517 + }
1518 + }
1519 +
1520 + // HTTP fetch step 5.5
1521 + switch (request.redirect) {
1522 + case 'error':
1523 + reject(new FetchError(`uri requested responds with a redirect, redirect mode is set to error: ${request.url}`, 'no-redirect'));
1524 + finalize();
1525 + return;
1526 + case 'manual':
1527 + // node-fetch-specific step: make manual redirect a bit easier to use by setting the Location header value to the resolved URL.
1528 + if (locationURL !== null) {
1529 + // handle corrupted header
1530 + try {
1531 + headers.set('Location', locationURL);
1532 + } catch (err) {
1533 + // istanbul ignore next: nodejs server prevent invalid response headers, we can't test this through normal request
1534 + reject(err);
1535 + }
1536 + }
1537 + break;
1538 + case 'follow':
1539 + // HTTP-redirect fetch step 2
1540 + if (locationURL === null) {
1541 + break;
1542 + }
1543 +
1544 + // HTTP-redirect fetch step 5
1545 + if (request.counter >= request.follow) {
1546 + reject(new FetchError(`maximum redirect reached at: ${request.url}`, 'max-redirect'));
1547 + finalize();
1548 + return;
1549 + }
1550 +
1551 + // HTTP-redirect fetch step 6 (counter increment)
1552 + // Create a new Request object.
1553 + const requestOpts = {
1554 + headers: new Headers(request.headers),
1555 + follow: request.follow,
1556 + counter: request.counter + 1,
1557 + agent: request.agent,
1558 + compress: request.compress,
1559 + method: request.method,
1560 + body: request.body,
1561 + signal: request.signal,
1562 + timeout: request.timeout,
1563 + size: request.size
1564 + };
1565 +
1566 + if (!isDomainOrSubdomain(request.url, locationURL)) {
1567 + for (const name of ['authorization', 'www-authenticate', 'cookie', 'cookie2']) {
1568 + requestOpts.headers.delete(name);
1569 + }
1570 + }
1571 +
1572 + // HTTP-redirect fetch step 9
1573 + if (res.statusCode !== 303 && request.body && getTotalBytes(request) === null) {
1574 + reject(new FetchError('Cannot follow redirect with body being a readable stream', 'unsupported-redirect'));
1575 + finalize();
1576 + return;
1577 + }
1578 +
1579 + // HTTP-redirect fetch step 11
1580 + if (res.statusCode === 303 || (res.statusCode === 301 || res.statusCode === 302) && request.method === 'POST') {
1581 + requestOpts.method = 'GET';
1582 + requestOpts.body = undefined;
1583 + requestOpts.headers.delete('content-length');
1584 + }
1585 +
1586 + // HTTP-redirect fetch step 15
1587 + resolve(fetch(new Request(locationURL, requestOpts)));
1588 + finalize();
1589 + return;
1590 + }
1591 + }
1592 +
1593 + // prepare response
1594 + res.once('end', function () {
1595 + if (signal) signal.removeEventListener('abort', abortAndFinalize);
1596 + });
1597 + let body = res.pipe(new PassThrough$1());
1598 +
1599 + const response_options = {
1600 + url: request.url,
1601 + status: res.statusCode,
1602 + statusText: res.statusMessage,
1603 + headers: headers,
1604 + size: request.size,
1605 + timeout: request.timeout,
1606 + counter: request.counter
1607 + };
1608 +
1609 + // HTTP-network fetch step 12.1.1.3
1610 + const codings = headers.get('Content-Encoding');
1611 +
1612 + // HTTP-network fetch step 12.1.1.4: handle content codings
1613 +
1614 + // in following scenarios we ignore compression support
1615 + // 1. compression support is disabled
1616 + // 2. HEAD request
1617 + // 3. no Content-Encoding header
1618 + // 4. no content response (204)
1619 + // 5. content not modified response (304)
1620 + if (!request.compress || request.method === 'HEAD' || codings === null || res.statusCode === 204 || res.statusCode === 304) {
1621 + response = new Response(body, response_options);
1622 + resolve(response);
1623 + return;
1624 + }
1625 +
1626 + // For Node v6+
1627 + // Be less strict when decoding compressed responses, since sometimes
1628 + // servers send slightly invalid responses that are still accepted
1629 + // by common browsers.
1630 + // Always using Z_SYNC_FLUSH is what cURL does.
1631 + const zlibOptions = {
1632 + flush: zlib.Z_SYNC_FLUSH,
1633 + finishFlush: zlib.Z_SYNC_FLUSH
1634 + };
1635 +
1636 + // for gzip
1637 + if (codings == 'gzip' || codings == 'x-gzip') {
1638 + body = body.pipe(zlib.createGunzip(zlibOptions));
1639 + response = new Response(body, response_options);
1640 + resolve(response);
1641 + return;
1642 + }
1643 +
1644 + // for deflate
1645 + if (codings == 'deflate' || codings == 'x-deflate') {
1646 + // handle the infamous raw deflate response from old servers
1647 + // a hack for old IIS and Apache servers
1648 + const raw = res.pipe(new PassThrough$1());
1649 + raw.once('data', function (chunk) {
1650 + // see http://stackoverflow.com/questions/37519828
1651 + if ((chunk[0] & 0x0F) === 0x08) {
1652 + body = body.pipe(zlib.createInflate());
1653 + } else {
1654 + body = body.pipe(zlib.createInflateRaw());
1655 + }
1656 + response = new Response(body, response_options);
1657 + resolve(response);
1658 + });
1659 + return;
1660 + }
1661 +
1662 + // for br
1663 + if (codings == 'br' && typeof zlib.createBrotliDecompress === 'function') {
1664 + body = body.pipe(zlib.createBrotliDecompress());
1665 + response = new Response(body, response_options);
1666 + resolve(response);
1667 + return;
1668 + }
1669 +
1670 + // otherwise, use response as-is
1671 + response = new Response(body, response_options);
1672 + resolve(response);
1673 + });
1674 +
1675 + writeToStream(req, request);
1676 + });
1677 +}
1678 +/**
1679 + * Redirect code matching
1680 + *
1681 + * @param Number code Status code
1682 + * @return Boolean
1683 + */
1684 +fetch.isRedirect = function (code) {
1685 + return code === 301 || code === 302 || code === 303 || code === 307 || code === 308;
1686 +};
1687 +
1688 +// expose Promise
1689 +fetch.Promise = global.Promise;
1690 +
1691 +module.exports = exports = fetch;
1692 +Object.defineProperty(exports, "__esModule", { value: true });
1693 +exports.default = exports;
1694 +exports.Headers = Headers;
1695 +exports.Request = Request;
1696 +exports.Response = Response;
1697 +exports.FetchError = FetchError;
1 +import Stream from 'stream';
2 +import http from 'http';
3 +import Url from 'url';
4 +import whatwgUrl from 'whatwg-url';
5 +import https from 'https';
6 +import zlib from 'zlib';
7 +
8 +// Based on https://github.com/tmpvar/jsdom/blob/aa85b2abf07766ff7bf5c1f6daafb3726f2f2db5/lib/jsdom/living/blob.js
9 +
10 +// fix for "Readable" isn't a named export issue
11 +const Readable = Stream.Readable;
12 +
13 +const BUFFER = Symbol('buffer');
14 +const TYPE = Symbol('type');
15 +
16 +class Blob {
17 + constructor() {
18 + this[TYPE] = '';
19 +
20 + const blobParts = arguments[0];
21 + const options = arguments[1];
22 +
23 + const buffers = [];
24 + let size = 0;
25 +
26 + if (blobParts) {
27 + const a = blobParts;
28 + const length = Number(a.length);
29 + for (let i = 0; i < length; i++) {
30 + const element = a[i];
31 + let buffer;
32 + if (element instanceof Buffer) {
33 + buffer = element;
34 + } else if (ArrayBuffer.isView(element)) {
35 + buffer = Buffer.from(element.buffer, element.byteOffset, element.byteLength);
36 + } else if (element instanceof ArrayBuffer) {
37 + buffer = Buffer.from(element);
38 + } else if (element instanceof Blob) {
39 + buffer = element[BUFFER];
40 + } else {
41 + buffer = Buffer.from(typeof element === 'string' ? element : String(element));
42 + }
43 + size += buffer.length;
44 + buffers.push(buffer);
45 + }
46 + }
47 +
48 + this[BUFFER] = Buffer.concat(buffers);
49 +
50 + let type = options && options.type !== undefined && String(options.type).toLowerCase();
51 + if (type && !/[^\u0020-\u007E]/.test(type)) {
52 + this[TYPE] = type;
53 + }
54 + }
55 + get size() {
56 + return this[BUFFER].length;
57 + }
58 + get type() {
59 + return this[TYPE];
60 + }
61 + text() {
62 + return Promise.resolve(this[BUFFER].toString());
63 + }
64 + arrayBuffer() {
65 + const buf = this[BUFFER];
66 + const ab = buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
67 + return Promise.resolve(ab);
68 + }
69 + stream() {
70 + const readable = new Readable();
71 + readable._read = function () {};
72 + readable.push(this[BUFFER]);
73 + readable.push(null);
74 + return readable;
75 + }
76 + toString() {
77 + return '[object Blob]';
78 + }
79 + slice() {
80 + const size = this.size;
81 +
82 + const start = arguments[0];
83 + const end = arguments[1];
84 + let relativeStart, relativeEnd;
85 + if (start === undefined) {
86 + relativeStart = 0;
87 + } else if (start < 0) {
88 + relativeStart = Math.max(size + start, 0);
89 + } else {
90 + relativeStart = Math.min(start, size);
91 + }
92 + if (end === undefined) {
93 + relativeEnd = size;
94 + } else if (end < 0) {
95 + relativeEnd = Math.max(size + end, 0);
96 + } else {
97 + relativeEnd = Math.min(end, size);
98 + }
99 + const span = Math.max(relativeEnd - relativeStart, 0);
100 +
101 + const buffer = this[BUFFER];
102 + const slicedBuffer = buffer.slice(relativeStart, relativeStart + span);
103 + const blob = new Blob([], { type: arguments[2] });
104 + blob[BUFFER] = slicedBuffer;
105 + return blob;
106 + }
107 +}
108 +
109 +Object.defineProperties(Blob.prototype, {
110 + size: { enumerable: true },
111 + type: { enumerable: true },
112 + slice: { enumerable: true }
113 +});
114 +
115 +Object.defineProperty(Blob.prototype, Symbol.toStringTag, {
116 + value: 'Blob',
117 + writable: false,
118 + enumerable: false,
119 + configurable: true
120 +});
121 +
122 +/**
123 + * fetch-error.js
124 + *
125 + * FetchError interface for operational errors
126 + */
127 +
128 +/**
129 + * Create FetchError instance
130 + *
131 + * @param String message Error message for human
132 + * @param String type Error type for machine
133 + * @param String systemError For Node.js system error
134 + * @return FetchError
135 + */
136 +function FetchError(message, type, systemError) {
137 + Error.call(this, message);
138 +
139 + this.message = message;
140 + this.type = type;
141 +
142 + // when err.type is `system`, err.code contains system error code
143 + if (systemError) {
144 + this.code = this.errno = systemError.code;
145 + }
146 +
147 + // hide custom error implementation details from end-users
148 + Error.captureStackTrace(this, this.constructor);
149 +}
150 +
151 +FetchError.prototype = Object.create(Error.prototype);
152 +FetchError.prototype.constructor = FetchError;
153 +FetchError.prototype.name = 'FetchError';
154 +
155 +let convert;
156 +try {
157 + convert = require('encoding').convert;
158 +} catch (e) {}
159 +
160 +const INTERNALS = Symbol('Body internals');
161 +
162 +// fix an issue where "PassThrough" isn't a named export for node <10
163 +const PassThrough = Stream.PassThrough;
164 +
165 +/**
166 + * Body mixin
167 + *
168 + * Ref: https://fetch.spec.whatwg.org/#body
169 + *
170 + * @param Stream body Readable stream
171 + * @param Object opts Response options
172 + * @return Void
173 + */
174 +function Body(body) {
175 + var _this = this;
176 +
177 + var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
178 + _ref$size = _ref.size;
179 +
180 + let size = _ref$size === undefined ? 0 : _ref$size;
181 + var _ref$timeout = _ref.timeout;
182 + let timeout = _ref$timeout === undefined ? 0 : _ref$timeout;
183 +
184 + if (body == null) {
185 + // body is undefined or null
186 + body = null;
187 + } else if (isURLSearchParams(body)) {
188 + // body is a URLSearchParams
189 + body = Buffer.from(body.toString());
190 + } else if (isBlob(body)) ; else if (Buffer.isBuffer(body)) ; else if (Object.prototype.toString.call(body) === '[object ArrayBuffer]') {
191 + // body is ArrayBuffer
192 + body = Buffer.from(body);
193 + } else if (ArrayBuffer.isView(body)) {
194 + // body is ArrayBufferView
195 + body = Buffer.from(body.buffer, body.byteOffset, body.byteLength);
196 + } else if (body instanceof Stream) ; else {
197 + // none of the above
198 + // coerce to string then buffer
199 + body = Buffer.from(String(body));
200 + }
201 + this[INTERNALS] = {
202 + body,
203 + disturbed: false,
204 + error: null
205 + };
206 + this.size = size;
207 + this.timeout = timeout;
208 +
209 + if (body instanceof Stream) {
210 + body.on('error', function (err) {
211 + const error = err.name === 'AbortError' ? err : new FetchError(`Invalid response body while trying to fetch ${_this.url}: ${err.message}`, 'system', err);
212 + _this[INTERNALS].error = error;
213 + });
214 + }
215 +}
216 +
217 +Body.prototype = {
218 + get body() {
219 + return this[INTERNALS].body;
220 + },
221 +
222 + get bodyUsed() {
223 + return this[INTERNALS].disturbed;
224 + },
225 +
226 + /**
227 + * Decode response as ArrayBuffer
228 + *
229 + * @return Promise
230 + */
231 + arrayBuffer() {
232 + return consumeBody.call(this).then(function (buf) {
233 + return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
234 + });
235 + },
236 +
237 + /**
238 + * Return raw response as Blob
239 + *
240 + * @return Promise
241 + */
242 + blob() {
243 + let ct = this.headers && this.headers.get('content-type') || '';
244 + return consumeBody.call(this).then(function (buf) {
245 + return Object.assign(
246 + // Prevent copying
247 + new Blob([], {
248 + type: ct.toLowerCase()
249 + }), {
250 + [BUFFER]: buf
251 + });
252 + });
253 + },
254 +
255 + /**
256 + * Decode response as json
257 + *
258 + * @return Promise
259 + */
260 + json() {
261 + var _this2 = this;
262 +
263 + return consumeBody.call(this).then(function (buffer) {
264 + try {
265 + return JSON.parse(buffer.toString());
266 + } catch (err) {
267 + return Body.Promise.reject(new FetchError(`invalid json response body at ${_this2.url} reason: ${err.message}`, 'invalid-json'));
268 + }
269 + });
270 + },
271 +
272 + /**
273 + * Decode response as text
274 + *
275 + * @return Promise
276 + */
277 + text() {
278 + return consumeBody.call(this).then(function (buffer) {
279 + return buffer.toString();
280 + });
281 + },
282 +
283 + /**
284 + * Decode response as buffer (non-spec api)
285 + *
286 + * @return Promise
287 + */
288 + buffer() {
289 + return consumeBody.call(this);
290 + },
291 +
292 + /**
293 + * Decode response as text, while automatically detecting the encoding and
294 + * trying to decode to UTF-8 (non-spec api)
295 + *
296 + * @return Promise
297 + */
298 + textConverted() {
299 + var _this3 = this;
300 +
301 + return consumeBody.call(this).then(function (buffer) {
302 + return convertBody(buffer, _this3.headers);
303 + });
304 + }
305 +};
306 +
307 +// In browsers, all properties are enumerable.
308 +Object.defineProperties(Body.prototype, {
309 + body: { enumerable: true },
310 + bodyUsed: { enumerable: true },
311 + arrayBuffer: { enumerable: true },
312 + blob: { enumerable: true },
313 + json: { enumerable: true },
314 + text: { enumerable: true }
315 +});
316 +
317 +Body.mixIn = function (proto) {
318 + for (const name of Object.getOwnPropertyNames(Body.prototype)) {
319 + // istanbul ignore else: future proof
320 + if (!(name in proto)) {
321 + const desc = Object.getOwnPropertyDescriptor(Body.prototype, name);
322 + Object.defineProperty(proto, name, desc);
323 + }
324 + }
325 +};
326 +
327 +/**
328 + * Consume and convert an entire Body to a Buffer.
329 + *
330 + * Ref: https://fetch.spec.whatwg.org/#concept-body-consume-body
331 + *
332 + * @return Promise
333 + */
334 +function consumeBody() {
335 + var _this4 = this;
336 +
337 + if (this[INTERNALS].disturbed) {
338 + return Body.Promise.reject(new TypeError(`body used already for: ${this.url}`));
339 + }
340 +
341 + this[INTERNALS].disturbed = true;
342 +
343 + if (this[INTERNALS].error) {
344 + return Body.Promise.reject(this[INTERNALS].error);
345 + }
346 +
347 + let body = this.body;
348 +
349 + // body is null
350 + if (body === null) {
351 + return Body.Promise.resolve(Buffer.alloc(0));
352 + }
353 +
354 + // body is blob
355 + if (isBlob(body)) {
356 + body = body.stream();
357 + }
358 +
359 + // body is buffer
360 + if (Buffer.isBuffer(body)) {
361 + return Body.Promise.resolve(body);
362 + }
363 +
364 + // istanbul ignore if: should never happen
365 + if (!(body instanceof Stream)) {
366 + return Body.Promise.resolve(Buffer.alloc(0));
367 + }
368 +
369 + // body is stream
370 + // get ready to actually consume the body
371 + let accum = [];
372 + let accumBytes = 0;
373 + let abort = false;
374 +
375 + return new Body.Promise(function (resolve, reject) {
376 + let resTimeout;
377 +
378 + // allow timeout on slow response body
379 + if (_this4.timeout) {
380 + resTimeout = setTimeout(function () {
381 + abort = true;
382 + reject(new FetchError(`Response timeout while trying to fetch ${_this4.url} (over ${_this4.timeout}ms)`, 'body-timeout'));
383 + }, _this4.timeout);
384 + }
385 +
386 + // handle stream errors
387 + body.on('error', function (err) {
388 + if (err.name === 'AbortError') {
389 + // if the request was aborted, reject with this Error
390 + abort = true;
391 + reject(err);
392 + } else {
393 + // other errors, such as incorrect content-encoding
394 + reject(new FetchError(`Invalid response body while trying to fetch ${_this4.url}: ${err.message}`, 'system', err));
395 + }
396 + });
397 +
398 + body.on('data', function (chunk) {
399 + if (abort || chunk === null) {
400 + return;
401 + }
402 +
403 + if (_this4.size && accumBytes + chunk.length > _this4.size) {
404 + abort = true;
405 + reject(new FetchError(`content size at ${_this4.url} over limit: ${_this4.size}`, 'max-size'));
406 + return;
407 + }
408 +
409 + accumBytes += chunk.length;
410 + accum.push(chunk);
411 + });
412 +
413 + body.on('end', function () {
414 + if (abort) {
415 + return;
416 + }
417 +
418 + clearTimeout(resTimeout);
419 +
420 + try {
421 + resolve(Buffer.concat(accum, accumBytes));
422 + } catch (err) {
423 + // handle streams that have accumulated too much data (issue #414)
424 + reject(new FetchError(`Could not create Buffer from response body for ${_this4.url}: ${err.message}`, 'system', err));
425 + }
426 + });
427 + });
428 +}
429 +
430 +/**
431 + * Detect buffer encoding and convert to target encoding
432 + * ref: http://www.w3.org/TR/2011/WD-html5-20110113/parsing.html#determining-the-character-encoding
433 + *
434 + * @param Buffer buffer Incoming buffer
435 + * @param String encoding Target encoding
436 + * @return String
437 + */
438 +function convertBody(buffer, headers) {
439 + if (typeof convert !== 'function') {
440 + throw new Error('The package `encoding` must be installed to use the textConverted() function');
441 + }
442 +
443 + const ct = headers.get('content-type');
444 + let charset = 'utf-8';
445 + let res, str;
446 +
447 + // header
448 + if (ct) {
449 + res = /charset=([^;]*)/i.exec(ct);
450 + }
451 +
452 + // no charset in content type, peek at response body for at most 1024 bytes
453 + str = buffer.slice(0, 1024).toString();
454 +
455 + // html5
456 + if (!res && str) {
457 + res = /<meta.+?charset=(['"])(.+?)\1/i.exec(str);
458 + }
459 +
460 + // html4
461 + if (!res && str) {
462 + res = /<meta[\s]+?http-equiv=(['"])content-type\1[\s]+?content=(['"])(.+?)\2/i.exec(str);
463 + if (!res) {
464 + res = /<meta[\s]+?content=(['"])(.+?)\1[\s]+?http-equiv=(['"])content-type\3/i.exec(str);
465 + if (res) {
466 + res.pop(); // drop last quote
467 + }
468 + }
469 +
470 + if (res) {
471 + res = /charset=(.*)/i.exec(res.pop());
472 + }
473 + }
474 +
475 + // xml
476 + if (!res && str) {
477 + res = /<\?xml.+?encoding=(['"])(.+?)\1/i.exec(str);
478 + }
479 +
480 + // found charset
481 + if (res) {
482 + charset = res.pop();
483 +
484 + // prevent decode issues when sites use incorrect encoding
485 + // ref: https://hsivonen.fi/encoding-menu/
486 + if (charset === 'gb2312' || charset === 'gbk') {
487 + charset = 'gb18030';
488 + }
489 + }
490 +
491 + // turn raw buffers into a single utf-8 buffer
492 + return convert(buffer, 'UTF-8', charset).toString();
493 +}
494 +
495 +/**
496 + * Detect a URLSearchParams object
497 + * ref: https://github.com/bitinn/node-fetch/issues/296#issuecomment-307598143
498 + *
499 + * @param Object obj Object to detect by type or brand
500 + * @return String
501 + */
502 +function isURLSearchParams(obj) {
503 + // Duck-typing as a necessary condition.
504 + 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') {
505 + return false;
506 + }
507 +
508 + // Brand-checking and more duck-typing as optional condition.
509 + return obj.constructor.name === 'URLSearchParams' || Object.prototype.toString.call(obj) === '[object URLSearchParams]' || typeof obj.sort === 'function';
510 +}
511 +
512 +/**
513 + * Check if `obj` is a W3C `Blob` object (which `File` inherits from)
514 + * @param {*} obj
515 + * @return {boolean}
516 + */
517 +function isBlob(obj) {
518 + 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]);
519 +}
520 +
521 +/**
522 + * Clone body given Res/Req instance
523 + *
524 + * @param Mixed instance Response or Request instance
525 + * @return Mixed
526 + */
527 +function clone(instance) {
528 + let p1, p2;
529 + let body = instance.body;
530 +
531 + // don't allow cloning a used body
532 + if (instance.bodyUsed) {
533 + throw new Error('cannot clone body after it is used');
534 + }
535 +
536 + // check that body is a stream and not form-data object
537 + // note: we can't clone the form-data object without having it as a dependency
538 + if (body instanceof Stream && typeof body.getBoundary !== 'function') {
539 + // tee instance body
540 + p1 = new PassThrough();
541 + p2 = new PassThrough();
542 + body.pipe(p1);
543 + body.pipe(p2);
544 + // set instance body to teed body and return the other teed body
545 + instance[INTERNALS].body = p1;
546 + body = p2;
547 + }
548 +
549 + return body;
550 +}
551 +
552 +/**
553 + * Performs the operation "extract a `Content-Type` value from |object|" as
554 + * specified in the specification:
555 + * https://fetch.spec.whatwg.org/#concept-bodyinit-extract
556 + *
557 + * This function assumes that instance.body is present.
558 + *
559 + * @param Mixed instance Any options.body input
560 + */
561 +function extractContentType(body) {
562 + if (body === null) {
563 + // body is null
564 + return null;
565 + } else if (typeof body === 'string') {
566 + // body is string
567 + return 'text/plain;charset=UTF-8';
568 + } else if (isURLSearchParams(body)) {
569 + // body is a URLSearchParams
570 + return 'application/x-www-form-urlencoded;charset=UTF-8';
571 + } else if (isBlob(body)) {
572 + // body is blob
573 + return body.type || null;
574 + } else if (Buffer.isBuffer(body)) {
575 + // body is buffer
576 + return null;
577 + } else if (Object.prototype.toString.call(body) === '[object ArrayBuffer]') {
578 + // body is ArrayBuffer
579 + return null;
580 + } else if (ArrayBuffer.isView(body)) {
581 + // body is ArrayBufferView
582 + return null;
583 + } else if (typeof body.getBoundary === 'function') {
584 + // detect form data input from form-data module
585 + return `multipart/form-data;boundary=${body.getBoundary()}`;
586 + } else if (body instanceof Stream) {
587 + // body is stream
588 + // can't really do much about this
589 + return null;
590 + } else {
591 + // Body constructor defaults other things to string
592 + return 'text/plain;charset=UTF-8';
593 + }
594 +}
595 +
596 +/**
597 + * The Fetch Standard treats this as if "total bytes" is a property on the body.
598 + * For us, we have to explicitly get it with a function.
599 + *
600 + * ref: https://fetch.spec.whatwg.org/#concept-body-total-bytes
601 + *
602 + * @param Body instance Instance of Body
603 + * @return Number? Number of bytes, or null if not possible
604 + */
605 +function getTotalBytes(instance) {
606 + const body = instance.body;
607 +
608 +
609 + if (body === null) {
610 + // body is null
611 + return 0;
612 + } else if (isBlob(body)) {
613 + return body.size;
614 + } else if (Buffer.isBuffer(body)) {
615 + // body is buffer
616 + return body.length;
617 + } else if (body && typeof body.getLengthSync === 'function') {
618 + // detect form data input from form-data module
619 + if (body._lengthRetrievers && body._lengthRetrievers.length == 0 || // 1.x
620 + body.hasKnownLength && body.hasKnownLength()) {
621 + // 2.x
622 + return body.getLengthSync();
623 + }
624 + return null;
625 + } else {
626 + // body is stream
627 + return null;
628 + }
629 +}
630 +
631 +/**
632 + * Write a Body to a Node.js WritableStream (e.g. http.Request) object.
633 + *
634 + * @param Body instance Instance of Body
635 + * @return Void
636 + */
637 +function writeToStream(dest, instance) {
638 + const body = instance.body;
639 +
640 +
641 + if (body === null) {
642 + // body is null
643 + dest.end();
644 + } else if (isBlob(body)) {
645 + body.stream().pipe(dest);
646 + } else if (Buffer.isBuffer(body)) {
647 + // body is buffer
648 + dest.write(body);
649 + dest.end();
650 + } else {
651 + // body is stream
652 + body.pipe(dest);
653 + }
654 +}
655 +
656 +// expose Promise
657 +Body.Promise = global.Promise;
658 +
659 +/**
660 + * headers.js
661 + *
662 + * Headers class offers convenient helpers
663 + */
664 +
665 +const invalidTokenRegex = /[^\^_`a-zA-Z\-0-9!#$%&'*+.|~]/;
666 +const invalidHeaderCharRegex = /[^\t\x20-\x7e\x80-\xff]/;
667 +
668 +function validateName(name) {
669 + name = `${name}`;
670 + if (invalidTokenRegex.test(name) || name === '') {
671 + throw new TypeError(`${name} is not a legal HTTP header name`);
672 + }
673 +}
674 +
675 +function validateValue(value) {
676 + value = `${value}`;
677 + if (invalidHeaderCharRegex.test(value)) {
678 + throw new TypeError(`${value} is not a legal HTTP header value`);
679 + }
680 +}
681 +
682 +/**
683 + * Find the key in the map object given a header name.
684 + *
685 + * Returns undefined if not found.
686 + *
687 + * @param String name Header name
688 + * @return String|Undefined
689 + */
690 +function find(map, name) {
691 + name = name.toLowerCase();
692 + for (const key in map) {
693 + if (key.toLowerCase() === name) {
694 + return key;
695 + }
696 + }
697 + return undefined;
698 +}
699 +
700 +const MAP = Symbol('map');
701 +class Headers {
702 + /**
703 + * Headers class
704 + *
705 + * @param Object headers Response headers
706 + * @return Void
707 + */
708 + constructor() {
709 + let init = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : undefined;
710 +
711 + this[MAP] = Object.create(null);
712 +
713 + if (init instanceof Headers) {
714 + const rawHeaders = init.raw();
715 + const headerNames = Object.keys(rawHeaders);
716 +
717 + for (const headerName of headerNames) {
718 + for (const value of rawHeaders[headerName]) {
719 + this.append(headerName, value);
720 + }
721 + }
722 +
723 + return;
724 + }
725 +
726 + // We don't worry about converting prop to ByteString here as append()
727 + // will handle it.
728 + if (init == null) ; else if (typeof init === 'object') {
729 + const method = init[Symbol.iterator];
730 + if (method != null) {
731 + if (typeof method !== 'function') {
732 + throw new TypeError('Header pairs must be iterable');
733 + }
734 +
735 + // sequence<sequence<ByteString>>
736 + // Note: per spec we have to first exhaust the lists then process them
737 + const pairs = [];
738 + for (const pair of init) {
739 + if (typeof pair !== 'object' || typeof pair[Symbol.iterator] !== 'function') {
740 + throw new TypeError('Each header pair must be iterable');
741 + }
742 + pairs.push(Array.from(pair));
743 + }
744 +
745 + for (const pair of pairs) {
746 + if (pair.length !== 2) {
747 + throw new TypeError('Each header pair must be a name/value tuple');
748 + }
749 + this.append(pair[0], pair[1]);
750 + }
751 + } else {
752 + // record<ByteString, ByteString>
753 + for (const key of Object.keys(init)) {
754 + const value = init[key];
755 + this.append(key, value);
756 + }
757 + }
758 + } else {
759 + throw new TypeError('Provided initializer must be an object');
760 + }
761 + }
762 +
763 + /**
764 + * Return combined header value given name
765 + *
766 + * @param String name Header name
767 + * @return Mixed
768 + */
769 + get(name) {
770 + name = `${name}`;
771 + validateName(name);
772 + const key = find(this[MAP], name);
773 + if (key === undefined) {
774 + return null;
775 + }
776 +
777 + return this[MAP][key].join(', ');
778 + }
779 +
780 + /**
781 + * Iterate over all headers
782 + *
783 + * @param Function callback Executed for each item with parameters (value, name, thisArg)
784 + * @param Boolean thisArg `this` context for callback function
785 + * @return Void
786 + */
787 + forEach(callback) {
788 + let thisArg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined;
789 +
790 + let pairs = getHeaders(this);
791 + let i = 0;
792 + while (i < pairs.length) {
793 + var _pairs$i = pairs[i];
794 + const name = _pairs$i[0],
795 + value = _pairs$i[1];
796 +
797 + callback.call(thisArg, value, name, this);
798 + pairs = getHeaders(this);
799 + i++;
800 + }
801 + }
802 +
803 + /**
804 + * Overwrite header values given name
805 + *
806 + * @param String name Header name
807 + * @param String value Header value
808 + * @return Void
809 + */
810 + set(name, value) {
811 + name = `${name}`;
812 + value = `${value}`;
813 + validateName(name);
814 + validateValue(value);
815 + const key = find(this[MAP], name);
816 + this[MAP][key !== undefined ? key : name] = [value];
817 + }
818 +
819 + /**
820 + * Append a value onto existing header
821 + *
822 + * @param String name Header name
823 + * @param String value Header value
824 + * @return Void
825 + */
826 + append(name, value) {
827 + name = `${name}`;
828 + value = `${value}`;
829 + validateName(name);
830 + validateValue(value);
831 + const key = find(this[MAP], name);
832 + if (key !== undefined) {
833 + this[MAP][key].push(value);
834 + } else {
835 + this[MAP][name] = [value];
836 + }
837 + }
838 +
839 + /**
840 + * Check for header name existence
841 + *
842 + * @param String name Header name
843 + * @return Boolean
844 + */
845 + has(name) {
846 + name = `${name}`;
847 + validateName(name);
848 + return find(this[MAP], name) !== undefined;
849 + }
850 +
851 + /**
852 + * Delete all header values given name
853 + *
854 + * @param String name Header name
855 + * @return Void
856 + */
857 + delete(name) {
858 + name = `${name}`;
859 + validateName(name);
860 + const key = find(this[MAP], name);
861 + if (key !== undefined) {
862 + delete this[MAP][key];
863 + }
864 + }
865 +
866 + /**
867 + * Return raw headers (non-spec api)
868 + *
869 + * @return Object
870 + */
871 + raw() {
872 + return this[MAP];
873 + }
874 +
875 + /**
876 + * Get an iterator on keys.
877 + *
878 + * @return Iterator
879 + */
880 + keys() {
881 + return createHeadersIterator(this, 'key');
882 + }
883 +
884 + /**
885 + * Get an iterator on values.
886 + *
887 + * @return Iterator
888 + */
889 + values() {
890 + return createHeadersIterator(this, 'value');
891 + }
892 +
893 + /**
894 + * Get an iterator on entries.
895 + *
896 + * This is the default iterator of the Headers object.
897 + *
898 + * @return Iterator
899 + */
900 + [Symbol.iterator]() {
901 + return createHeadersIterator(this, 'key+value');
902 + }
903 +}
904 +Headers.prototype.entries = Headers.prototype[Symbol.iterator];
905 +
906 +Object.defineProperty(Headers.prototype, Symbol.toStringTag, {
907 + value: 'Headers',
908 + writable: false,
909 + enumerable: false,
910 + configurable: true
911 +});
912 +
913 +Object.defineProperties(Headers.prototype, {
914 + get: { enumerable: true },
915 + forEach: { enumerable: true },
916 + set: { enumerable: true },
917 + append: { enumerable: true },
918 + has: { enumerable: true },
919 + delete: { enumerable: true },
920 + keys: { enumerable: true },
921 + values: { enumerable: true },
922 + entries: { enumerable: true }
923 +});
924 +
925 +function getHeaders(headers) {
926 + let kind = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'key+value';
927 +
928 + const keys = Object.keys(headers[MAP]).sort();
929 + return keys.map(kind === 'key' ? function (k) {
930 + return k.toLowerCase();
931 + } : kind === 'value' ? function (k) {
932 + return headers[MAP][k].join(', ');
933 + } : function (k) {
934 + return [k.toLowerCase(), headers[MAP][k].join(', ')];
935 + });
936 +}
937 +
938 +const INTERNAL = Symbol('internal');
939 +
940 +function createHeadersIterator(target, kind) {
941 + const iterator = Object.create(HeadersIteratorPrototype);
942 + iterator[INTERNAL] = {
943 + target,
944 + kind,
945 + index: 0
946 + };
947 + return iterator;
948 +}
949 +
950 +const HeadersIteratorPrototype = Object.setPrototypeOf({
951 + next() {
952 + // istanbul ignore if
953 + if (!this || Object.getPrototypeOf(this) !== HeadersIteratorPrototype) {
954 + throw new TypeError('Value of `this` is not a HeadersIterator');
955 + }
956 +
957 + var _INTERNAL = this[INTERNAL];
958 + const target = _INTERNAL.target,
959 + kind = _INTERNAL.kind,
960 + index = _INTERNAL.index;
961 +
962 + const values = getHeaders(target, kind);
963 + const len = values.length;
964 + if (index >= len) {
965 + return {
966 + value: undefined,
967 + done: true
968 + };
969 + }
970 +
971 + this[INTERNAL].index = index + 1;
972 +
973 + return {
974 + value: values[index],
975 + done: false
976 + };
977 + }
978 +}, Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]())));
979 +
980 +Object.defineProperty(HeadersIteratorPrototype, Symbol.toStringTag, {
981 + value: 'HeadersIterator',
982 + writable: false,
983 + enumerable: false,
984 + configurable: true
985 +});
986 +
987 +/**
988 + * Export the Headers object in a form that Node.js can consume.
989 + *
990 + * @param Headers headers
991 + * @return Object
992 + */
993 +function exportNodeCompatibleHeaders(headers) {
994 + const obj = Object.assign({ __proto__: null }, headers[MAP]);
995 +
996 + // http.request() only supports string as Host header. This hack makes
997 + // specifying custom Host header possible.
998 + const hostHeaderKey = find(headers[MAP], 'Host');
999 + if (hostHeaderKey !== undefined) {
1000 + obj[hostHeaderKey] = obj[hostHeaderKey][0];
1001 + }
1002 +
1003 + return obj;
1004 +}
1005 +
1006 +/**
1007 + * Create a Headers object from an object of headers, ignoring those that do
1008 + * not conform to HTTP grammar productions.
1009 + *
1010 + * @param Object obj Object of headers
1011 + * @return Headers
1012 + */
1013 +function createHeadersLenient(obj) {
1014 + const headers = new Headers();
1015 + for (const name of Object.keys(obj)) {
1016 + if (invalidTokenRegex.test(name)) {
1017 + continue;
1018 + }
1019 + if (Array.isArray(obj[name])) {
1020 + for (const val of obj[name]) {
1021 + if (invalidHeaderCharRegex.test(val)) {
1022 + continue;
1023 + }
1024 + if (headers[MAP][name] === undefined) {
1025 + headers[MAP][name] = [val];
1026 + } else {
1027 + headers[MAP][name].push(val);
1028 + }
1029 + }
1030 + } else if (!invalidHeaderCharRegex.test(obj[name])) {
1031 + headers[MAP][name] = [obj[name]];
1032 + }
1033 + }
1034 + return headers;
1035 +}
1036 +
1037 +const INTERNALS$1 = Symbol('Response internals');
1038 +
1039 +// fix an issue where "STATUS_CODES" aren't a named export for node <10
1040 +const STATUS_CODES = http.STATUS_CODES;
1041 +
1042 +/**
1043 + * Response class
1044 + *
1045 + * @param Stream body Readable stream
1046 + * @param Object opts Response options
1047 + * @return Void
1048 + */
1049 +class Response {
1050 + constructor() {
1051 + let body = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
1052 + let opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1053 +
1054 + Body.call(this, body, opts);
1055 +
1056 + const status = opts.status || 200;
1057 + const headers = new Headers(opts.headers);
1058 +
1059 + if (body != null && !headers.has('Content-Type')) {
1060 + const contentType = extractContentType(body);
1061 + if (contentType) {
1062 + headers.append('Content-Type', contentType);
1063 + }
1064 + }
1065 +
1066 + this[INTERNALS$1] = {
1067 + url: opts.url,
1068 + status,
1069 + statusText: opts.statusText || STATUS_CODES[status],
1070 + headers,
1071 + counter: opts.counter
1072 + };
1073 + }
1074 +
1075 + get url() {
1076 + return this[INTERNALS$1].url || '';
1077 + }
1078 +
1079 + get status() {
1080 + return this[INTERNALS$1].status;
1081 + }
1082 +
1083 + /**
1084 + * Convenience property representing if the request ended normally
1085 + */
1086 + get ok() {
1087 + return this[INTERNALS$1].status >= 200 && this[INTERNALS$1].status < 300;
1088 + }
1089 +
1090 + get redirected() {
1091 + return this[INTERNALS$1].counter > 0;
1092 + }
1093 +
1094 + get statusText() {
1095 + return this[INTERNALS$1].statusText;
1096 + }
1097 +
1098 + get headers() {
1099 + return this[INTERNALS$1].headers;
1100 + }
1101 +
1102 + /**
1103 + * Clone this response
1104 + *
1105 + * @return Response
1106 + */
1107 + clone() {
1108 + return new Response(clone(this), {
1109 + url: this.url,
1110 + status: this.status,
1111 + statusText: this.statusText,
1112 + headers: this.headers,
1113 + ok: this.ok,
1114 + redirected: this.redirected
1115 + });
1116 + }
1117 +}
1118 +
1119 +Body.mixIn(Response.prototype);
1120 +
1121 +Object.defineProperties(Response.prototype, {
1122 + url: { enumerable: true },
1123 + status: { enumerable: true },
1124 + ok: { enumerable: true },
1125 + redirected: { enumerable: true },
1126 + statusText: { enumerable: true },
1127 + headers: { enumerable: true },
1128 + clone: { enumerable: true }
1129 +});
1130 +
1131 +Object.defineProperty(Response.prototype, Symbol.toStringTag, {
1132 + value: 'Response',
1133 + writable: false,
1134 + enumerable: false,
1135 + configurable: true
1136 +});
1137 +
1138 +const INTERNALS$2 = Symbol('Request internals');
1139 +const URL = Url.URL || whatwgUrl.URL;
1140 +
1141 +// fix an issue where "format", "parse" aren't a named export for node <10
1142 +const parse_url = Url.parse;
1143 +const format_url = Url.format;
1144 +
1145 +/**
1146 + * Wrapper around `new URL` to handle arbitrary URLs
1147 + *
1148 + * @param {string} urlStr
1149 + * @return {void}
1150 + */
1151 +function parseURL(urlStr) {
1152 + /*
1153 + Check whether the URL is absolute or not
1154 + Scheme: https://tools.ietf.org/html/rfc3986#section-3.1
1155 + Absolute URL: https://tools.ietf.org/html/rfc3986#section-4.3
1156 + */
1157 + if (/^[a-zA-Z][a-zA-Z\d+\-.]*:/.exec(urlStr)) {
1158 + urlStr = new URL(urlStr).toString();
1159 + }
1160 +
1161 + // Fallback to old implementation for arbitrary URLs
1162 + return parse_url(urlStr);
1163 +}
1164 +
1165 +const streamDestructionSupported = 'destroy' in Stream.Readable.prototype;
1166 +
1167 +/**
1168 + * Check if a value is an instance of Request.
1169 + *
1170 + * @param Mixed input
1171 + * @return Boolean
1172 + */
1173 +function isRequest(input) {
1174 + return typeof input === 'object' && typeof input[INTERNALS$2] === 'object';
1175 +}
1176 +
1177 +function isAbortSignal(signal) {
1178 + const proto = signal && typeof signal === 'object' && Object.getPrototypeOf(signal);
1179 + return !!(proto && proto.constructor.name === 'AbortSignal');
1180 +}
1181 +
1182 +/**
1183 + * Request class
1184 + *
1185 + * @param Mixed input Url or Request instance
1186 + * @param Object init Custom options
1187 + * @return Void
1188 + */
1189 +class Request {
1190 + constructor(input) {
1191 + let init = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1192 +
1193 + let parsedURL;
1194 +
1195 + // normalize input
1196 + if (!isRequest(input)) {
1197 + if (input && input.href) {
1198 + // in order to support Node.js' Url objects; though WHATWG's URL objects
1199 + // will fall into this branch also (since their `toString()` will return
1200 + // `href` property anyway)
1201 + parsedURL = parseURL(input.href);
1202 + } else {
1203 + // coerce input to a string before attempting to parse
1204 + parsedURL = parseURL(`${input}`);
1205 + }
1206 + input = {};
1207 + } else {
1208 + parsedURL = parseURL(input.url);
1209 + }
1210 +
1211 + let method = init.method || input.method || 'GET';
1212 + method = method.toUpperCase();
1213 +
1214 + if ((init.body != null || isRequest(input) && input.body !== null) && (method === 'GET' || method === 'HEAD')) {
1215 + throw new TypeError('Request with GET/HEAD method cannot have body');
1216 + }
1217 +
1218 + let inputBody = init.body != null ? init.body : isRequest(input) && input.body !== null ? clone(input) : null;
1219 +
1220 + Body.call(this, inputBody, {
1221 + timeout: init.timeout || input.timeout || 0,
1222 + size: init.size || input.size || 0
1223 + });
1224 +
1225 + const headers = new Headers(init.headers || input.headers || {});
1226 +
1227 + if (inputBody != null && !headers.has('Content-Type')) {
1228 + const contentType = extractContentType(inputBody);
1229 + if (contentType) {
1230 + headers.append('Content-Type', contentType);
1231 + }
1232 + }
1233 +
1234 + let signal = isRequest(input) ? input.signal : null;
1235 + if ('signal' in init) signal = init.signal;
1236 +
1237 + if (signal != null && !isAbortSignal(signal)) {
1238 + throw new TypeError('Expected signal to be an instanceof AbortSignal');
1239 + }
1240 +
1241 + this[INTERNALS$2] = {
1242 + method,
1243 + redirect: init.redirect || input.redirect || 'follow',
1244 + headers,
1245 + parsedURL,
1246 + signal
1247 + };
1248 +
1249 + // node-fetch-only options
1250 + this.follow = init.follow !== undefined ? init.follow : input.follow !== undefined ? input.follow : 20;
1251 + this.compress = init.compress !== undefined ? init.compress : input.compress !== undefined ? input.compress : true;
1252 + this.counter = init.counter || input.counter || 0;
1253 + this.agent = init.agent || input.agent;
1254 + }
1255 +
1256 + get method() {
1257 + return this[INTERNALS$2].method;
1258 + }
1259 +
1260 + get url() {
1261 + return format_url(this[INTERNALS$2].parsedURL);
1262 + }
1263 +
1264 + get headers() {
1265 + return this[INTERNALS$2].headers;
1266 + }
1267 +
1268 + get redirect() {
1269 + return this[INTERNALS$2].redirect;
1270 + }
1271 +
1272 + get signal() {
1273 + return this[INTERNALS$2].signal;
1274 + }
1275 +
1276 + /**
1277 + * Clone this request
1278 + *
1279 + * @return Request
1280 + */
1281 + clone() {
1282 + return new Request(this);
1283 + }
1284 +}
1285 +
1286 +Body.mixIn(Request.prototype);
1287 +
1288 +Object.defineProperty(Request.prototype, Symbol.toStringTag, {
1289 + value: 'Request',
1290 + writable: false,
1291 + enumerable: false,
1292 + configurable: true
1293 +});
1294 +
1295 +Object.defineProperties(Request.prototype, {
1296 + method: { enumerable: true },
1297 + url: { enumerable: true },
1298 + headers: { enumerable: true },
1299 + redirect: { enumerable: true },
1300 + clone: { enumerable: true },
1301 + signal: { enumerable: true }
1302 +});
1303 +
1304 +/**
1305 + * Convert a Request to Node.js http request options.
1306 + *
1307 + * @param Request A Request instance
1308 + * @return Object The options object to be passed to http.request
1309 + */
1310 +function getNodeRequestOptions(request) {
1311 + const parsedURL = request[INTERNALS$2].parsedURL;
1312 + const headers = new Headers(request[INTERNALS$2].headers);
1313 +
1314 + // fetch step 1.3
1315 + if (!headers.has('Accept')) {
1316 + headers.set('Accept', '*/*');
1317 + }
1318 +
1319 + // Basic fetch
1320 + if (!parsedURL.protocol || !parsedURL.hostname) {
1321 + throw new TypeError('Only absolute URLs are supported');
1322 + }
1323 +
1324 + if (!/^https?:$/.test(parsedURL.protocol)) {
1325 + throw new TypeError('Only HTTP(S) protocols are supported');
1326 + }
1327 +
1328 + if (request.signal && request.body instanceof Stream.Readable && !streamDestructionSupported) {
1329 + throw new Error('Cancellation of streamed requests with AbortSignal is not supported in node < 8');
1330 + }
1331 +
1332 + // HTTP-network-or-cache fetch steps 2.4-2.7
1333 + let contentLengthValue = null;
1334 + if (request.body == null && /^(POST|PUT)$/i.test(request.method)) {
1335 + contentLengthValue = '0';
1336 + }
1337 + if (request.body != null) {
1338 + const totalBytes = getTotalBytes(request);
1339 + if (typeof totalBytes === 'number') {
1340 + contentLengthValue = String(totalBytes);
1341 + }
1342 + }
1343 + if (contentLengthValue) {
1344 + headers.set('Content-Length', contentLengthValue);
1345 + }
1346 +
1347 + // HTTP-network-or-cache fetch step 2.11
1348 + if (!headers.has('User-Agent')) {
1349 + headers.set('User-Agent', 'node-fetch/1.0 (+https://github.com/bitinn/node-fetch)');
1350 + }
1351 +
1352 + // HTTP-network-or-cache fetch step 2.15
1353 + if (request.compress && !headers.has('Accept-Encoding')) {
1354 + headers.set('Accept-Encoding', 'gzip,deflate');
1355 + }
1356 +
1357 + let agent = request.agent;
1358 + if (typeof agent === 'function') {
1359 + agent = agent(parsedURL);
1360 + }
1361 +
1362 + if (!headers.has('Connection') && !agent) {
1363 + headers.set('Connection', 'close');
1364 + }
1365 +
1366 + // HTTP-network fetch step 4.2
1367 + // chunked encoding is handled by Node.js
1368 +
1369 + return Object.assign({}, parsedURL, {
1370 + method: request.method,
1371 + headers: exportNodeCompatibleHeaders(headers),
1372 + agent
1373 + });
1374 +}
1375 +
1376 +/**
1377 + * abort-error.js
1378 + *
1379 + * AbortError interface for cancelled requests
1380 + */
1381 +
1382 +/**
1383 + * Create AbortError instance
1384 + *
1385 + * @param String message Error message for human
1386 + * @return AbortError
1387 + */
1388 +function AbortError(message) {
1389 + Error.call(this, message);
1390 +
1391 + this.type = 'aborted';
1392 + this.message = message;
1393 +
1394 + // hide custom error implementation details from end-users
1395 + Error.captureStackTrace(this, this.constructor);
1396 +}
1397 +
1398 +AbortError.prototype = Object.create(Error.prototype);
1399 +AbortError.prototype.constructor = AbortError;
1400 +AbortError.prototype.name = 'AbortError';
1401 +
1402 +const URL$1 = Url.URL || whatwgUrl.URL;
1403 +
1404 +// fix an issue where "PassThrough", "resolve" aren't a named export for node <10
1405 +const PassThrough$1 = Stream.PassThrough;
1406 +
1407 +const isDomainOrSubdomain = function isDomainOrSubdomain(destination, original) {
1408 + const orig = new URL$1(original).hostname;
1409 + const dest = new URL$1(destination).hostname;
1410 +
1411 + return orig === dest || orig[orig.length - dest.length - 1] === '.' && orig.endsWith(dest);
1412 +};
1413 +
1414 +/**
1415 + * Fetch function
1416 + *
1417 + * @param Mixed url Absolute url or Request instance
1418 + * @param Object opts Fetch options
1419 + * @return Promise
1420 + */
1421 +function fetch(url, opts) {
1422 +
1423 + // allow custom promise
1424 + if (!fetch.Promise) {
1425 + throw new Error('native promise missing, set fetch.Promise to your favorite alternative');
1426 + }
1427 +
1428 + Body.Promise = fetch.Promise;
1429 +
1430 + // wrap http.request into fetch
1431 + return new fetch.Promise(function (resolve, reject) {
1432 + // build request object
1433 + const request = new Request(url, opts);
1434 + const options = getNodeRequestOptions(request);
1435 +
1436 + const send = (options.protocol === 'https:' ? https : http).request;
1437 + const signal = request.signal;
1438 +
1439 + let response = null;
1440 +
1441 + const abort = function abort() {
1442 + let error = new AbortError('The user aborted a request.');
1443 + reject(error);
1444 + if (request.body && request.body instanceof Stream.Readable) {
1445 + request.body.destroy(error);
1446 + }
1447 + if (!response || !response.body) return;
1448 + response.body.emit('error', error);
1449 + };
1450 +
1451 + if (signal && signal.aborted) {
1452 + abort();
1453 + return;
1454 + }
1455 +
1456 + const abortAndFinalize = function abortAndFinalize() {
1457 + abort();
1458 + finalize();
1459 + };
1460 +
1461 + // send request
1462 + const req = send(options);
1463 + let reqTimeout;
1464 +
1465 + if (signal) {
1466 + signal.addEventListener('abort', abortAndFinalize);
1467 + }
1468 +
1469 + function finalize() {
1470 + req.abort();
1471 + if (signal) signal.removeEventListener('abort', abortAndFinalize);
1472 + clearTimeout(reqTimeout);
1473 + }
1474 +
1475 + if (request.timeout) {
1476 + req.once('socket', function (socket) {
1477 + reqTimeout = setTimeout(function () {
1478 + reject(new FetchError(`network timeout at: ${request.url}`, 'request-timeout'));
1479 + finalize();
1480 + }, request.timeout);
1481 + });
1482 + }
1483 +
1484 + req.on('error', function (err) {
1485 + reject(new FetchError(`request to ${request.url} failed, reason: ${err.message}`, 'system', err));
1486 + finalize();
1487 + });
1488 +
1489 + req.on('response', function (res) {
1490 + clearTimeout(reqTimeout);
1491 +
1492 + const headers = createHeadersLenient(res.headers);
1493 +
1494 + // HTTP fetch step 5
1495 + if (fetch.isRedirect(res.statusCode)) {
1496 + // HTTP fetch step 5.2
1497 + const location = headers.get('Location');
1498 +
1499 + // HTTP fetch step 5.3
1500 + let locationURL = null;
1501 + try {
1502 + locationURL = location === null ? null : new URL$1(location, request.url).toString();
1503 + } catch (err) {
1504 + // error here can only be invalid URL in Location: header
1505 + // do not throw when options.redirect == manual
1506 + // let the user extract the errorneous redirect URL
1507 + if (request.redirect !== 'manual') {
1508 + reject(new FetchError(`uri requested responds with an invalid redirect URL: ${location}`, 'invalid-redirect'));
1509 + finalize();
1510 + return;
1511 + }
1512 + }
1513 +
1514 + // HTTP fetch step 5.5
1515 + switch (request.redirect) {
1516 + case 'error':
1517 + reject(new FetchError(`uri requested responds with a redirect, redirect mode is set to error: ${request.url}`, 'no-redirect'));
1518 + finalize();
1519 + return;
1520 + case 'manual':
1521 + // node-fetch-specific step: make manual redirect a bit easier to use by setting the Location header value to the resolved URL.
1522 + if (locationURL !== null) {
1523 + // handle corrupted header
1524 + try {
1525 + headers.set('Location', locationURL);
1526 + } catch (err) {
1527 + // istanbul ignore next: nodejs server prevent invalid response headers, we can't test this through normal request
1528 + reject(err);
1529 + }
1530 + }
1531 + break;
1532 + case 'follow':
1533 + // HTTP-redirect fetch step 2
1534 + if (locationURL === null) {
1535 + break;
1536 + }
1537 +
1538 + // HTTP-redirect fetch step 5
1539 + if (request.counter >= request.follow) {
1540 + reject(new FetchError(`maximum redirect reached at: ${request.url}`, 'max-redirect'));
1541 + finalize();
1542 + return;
1543 + }
1544 +
1545 + // HTTP-redirect fetch step 6 (counter increment)
1546 + // Create a new Request object.
1547 + const requestOpts = {
1548 + headers: new Headers(request.headers),
1549 + follow: request.follow,
1550 + counter: request.counter + 1,
1551 + agent: request.agent,
1552 + compress: request.compress,
1553 + method: request.method,
1554 + body: request.body,
1555 + signal: request.signal,
1556 + timeout: request.timeout,
1557 + size: request.size
1558 + };
1559 +
1560 + if (!isDomainOrSubdomain(request.url, locationURL)) {
1561 + for (const name of ['authorization', 'www-authenticate', 'cookie', 'cookie2']) {
1562 + requestOpts.headers.delete(name);
1563 + }
1564 + }
1565 +
1566 + // HTTP-redirect fetch step 9
1567 + if (res.statusCode !== 303 && request.body && getTotalBytes(request) === null) {
1568 + reject(new FetchError('Cannot follow redirect with body being a readable stream', 'unsupported-redirect'));
1569 + finalize();
1570 + return;
1571 + }
1572 +
1573 + // HTTP-redirect fetch step 11
1574 + if (res.statusCode === 303 || (res.statusCode === 301 || res.statusCode === 302) && request.method === 'POST') {
1575 + requestOpts.method = 'GET';
1576 + requestOpts.body = undefined;
1577 + requestOpts.headers.delete('content-length');
1578 + }
1579 +
1580 + // HTTP-redirect fetch step 15
1581 + resolve(fetch(new Request(locationURL, requestOpts)));
1582 + finalize();
1583 + return;
1584 + }
1585 + }
1586 +
1587 + // prepare response
1588 + res.once('end', function () {
1589 + if (signal) signal.removeEventListener('abort', abortAndFinalize);
1590 + });
1591 + let body = res.pipe(new PassThrough$1());
1592 +
1593 + const response_options = {
1594 + url: request.url,
1595 + status: res.statusCode,
1596 + statusText: res.statusMessage,
1597 + headers: headers,
1598 + size: request.size,
1599 + timeout: request.timeout,
1600 + counter: request.counter
1601 + };
1602 +
1603 + // HTTP-network fetch step 12.1.1.3
1604 + const codings = headers.get('Content-Encoding');
1605 +
1606 + // HTTP-network fetch step 12.1.1.4: handle content codings
1607 +
1608 + // in following scenarios we ignore compression support
1609 + // 1. compression support is disabled
1610 + // 2. HEAD request
1611 + // 3. no Content-Encoding header
1612 + // 4. no content response (204)
1613 + // 5. content not modified response (304)
1614 + if (!request.compress || request.method === 'HEAD' || codings === null || res.statusCode === 204 || res.statusCode === 304) {
1615 + response = new Response(body, response_options);
1616 + resolve(response);
1617 + return;
1618 + }
1619 +
1620 + // For Node v6+
1621 + // Be less strict when decoding compressed responses, since sometimes
1622 + // servers send slightly invalid responses that are still accepted
1623 + // by common browsers.
1624 + // Always using Z_SYNC_FLUSH is what cURL does.
1625 + const zlibOptions = {
1626 + flush: zlib.Z_SYNC_FLUSH,
1627 + finishFlush: zlib.Z_SYNC_FLUSH
1628 + };
1629 +
1630 + // for gzip
1631 + if (codings == 'gzip' || codings == 'x-gzip') {
1632 + body = body.pipe(zlib.createGunzip(zlibOptions));
1633 + response = new Response(body, response_options);
1634 + resolve(response);
1635 + return;
1636 + }
1637 +
1638 + // for deflate
1639 + if (codings == 'deflate' || codings == 'x-deflate') {
1640 + // handle the infamous raw deflate response from old servers
1641 + // a hack for old IIS and Apache servers
1642 + const raw = res.pipe(new PassThrough$1());
1643 + raw.once('data', function (chunk) {
1644 + // see http://stackoverflow.com/questions/37519828
1645 + if ((chunk[0] & 0x0F) === 0x08) {
1646 + body = body.pipe(zlib.createInflate());
1647 + } else {
1648 + body = body.pipe(zlib.createInflateRaw());
1649 + }
1650 + response = new Response(body, response_options);
1651 + resolve(response);
1652 + });
1653 + return;
1654 + }
1655 +
1656 + // for br
1657 + if (codings == 'br' && typeof zlib.createBrotliDecompress === 'function') {
1658 + body = body.pipe(zlib.createBrotliDecompress());
1659 + response = new Response(body, response_options);
1660 + resolve(response);
1661 + return;
1662 + }
1663 +
1664 + // otherwise, use response as-is
1665 + response = new Response(body, response_options);
1666 + resolve(response);
1667 + });
1668 +
1669 + writeToStream(req, request);
1670 + });
1671 +}
1672 +/**
1673 + * Redirect code matching
1674 + *
1675 + * @param Number code Status code
1676 + * @return Boolean
1677 + */
1678 +fetch.isRedirect = function (code) {
1679 + return code === 301 || code === 302 || code === 303 || code === 307 || code === 308;
1680 +};
1681 +
1682 +// expose Promise
1683 +fetch.Promise = global.Promise;
1684 +
1685 +export default fetch;
1686 +export { Headers, Request, Response, FetchError };
1 +{
2 + "name": "node-fetch",
3 + "version": "2.6.7",
4 + "description": "A light-weight module that brings window.fetch to node.js",
5 + "main": "lib/index.js",
6 + "browser": "./browser.js",
7 + "module": "lib/index.mjs",
8 + "files": [
9 + "lib/index.js",
10 + "lib/index.mjs",
11 + "lib/index.es.js",
12 + "browser.js"
13 + ],
14 + "engines": {
15 + "node": "4.x || >=6.0.0"
16 + },
17 + "scripts": {
18 + "build": "cross-env BABEL_ENV=rollup rollup -c",
19 + "prepare": "npm run build",
20 + "test": "cross-env BABEL_ENV=test mocha --require babel-register --throw-deprecation test/test.js",
21 + "report": "cross-env BABEL_ENV=coverage nyc --reporter lcov --reporter text mocha -R spec test/test.js",
22 + "coverage": "cross-env BABEL_ENV=coverage nyc --reporter json --reporter text mocha -R spec test/test.js && codecov -f coverage/coverage-final.json"
23 + },
24 + "repository": {
25 + "type": "git",
26 + "url": "https://github.com/bitinn/node-fetch.git"
27 + },
28 + "keywords": [
29 + "fetch",
30 + "http",
31 + "promise"
32 + ],
33 + "author": "David Frank",
34 + "license": "MIT",
35 + "bugs": {
36 + "url": "https://github.com/bitinn/node-fetch/issues"
37 + },
38 + "homepage": "https://github.com/bitinn/node-fetch",
39 + "dependencies": {
40 + "whatwg-url": "^5.0.0"
41 + },
42 + "peerDependencies": {
43 + "encoding": "^0.1.0"
44 + },
45 + "peerDependenciesMeta": {
46 + "encoding": {
47 + "optional": true
48 + }
49 + },
50 + "devDependencies": {
51 + "@ungap/url-search-params": "^0.1.2",
52 + "abort-controller": "^1.1.0",
53 + "abortcontroller-polyfill": "^1.3.0",
54 + "babel-core": "^6.26.3",
55 + "babel-plugin-istanbul": "^4.1.6",
56 + "babel-preset-env": "^1.6.1",
57 + "babel-register": "^6.16.3",
58 + "chai": "^3.5.0",
59 + "chai-as-promised": "^7.1.1",
60 + "chai-iterator": "^1.1.1",
61 + "chai-string": "~1.3.0",
62 + "codecov": "3.3.0",
63 + "cross-env": "^5.2.0",
64 + "form-data": "^2.3.3",
65 + "is-builtin-module": "^1.0.0",
66 + "mocha": "^5.0.0",
67 + "nyc": "11.9.0",
68 + "parted": "^0.1.1",
69 + "promise": "^8.0.3",
70 + "resumer": "0.0.0",
71 + "rollup": "^0.63.4",
72 + "rollup-plugin-babel": "^3.0.7",
73 + "string-to-arraybuffer": "^1.0.2",
74 + "teeny-request": "3.7.0"
75 + }
76 +}
1 +Copyright (c) 2013, Deoxxa Development
2 +======================================
3 +All rights reserved.
4 +--------------------
5 +
6 +Redistribution and use in source and binary forms, with or without
7 +modification, are permitted provided that the following conditions are met:
8 +1. Redistributions of source code must retain the above copyright
9 + notice, this list of conditions and the following disclaimer.
10 +2. Redistributions in binary form must reproduce the above copyright
11 + notice, this list of conditions and the following disclaimer in the
12 + documentation and/or other materials provided with the distribution.
13 +3. Neither the name of Deoxxa Development nor the names of its contributors
14 + may be used to endorse or promote products derived from this software
15 + without specific prior written permission.
16 +
17 +THIS SOFTWARE IS PROVIDED BY DEOXXA DEVELOPMENT ''AS IS'' AND ANY
18 +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 +DISCLAIMED. IN NO EVENT SHALL DEOXXA DEVELOPMENT BE LIABLE FOR ANY
21 +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1 +# duplexer3 [![Build Status](https://travis-ci.org/floatdrop/duplexer3.svg?branch=master)](https://travis-ci.org/floatdrop/duplexer3) [![Coverage Status](https://coveralls.io/repos/floatdrop/duplexer3/badge.svg?branch=master&service=github)](https://coveralls.io/github/floatdrop/duplexer3?branch=master)
2 +
3 +Like [duplexer2](https://github.com/deoxxa/duplexer2) but using Streams3 without readable-stream dependency
4 +
5 +```javascript
6 +var stream = require("stream");
7 +
8 +var duplexer3 = require("duplexer3");
9 +
10 +var writable = new stream.Writable({objectMode: true}),
11 + readable = new stream.Readable({objectMode: true});
12 +
13 +writable._write = function _write(input, encoding, done) {
14 + if (readable.push(input)) {
15 + return done();
16 + } else {
17 + readable.once("drain", done);
18 + }
19 +};
20 +
21 +readable._read = function _read(n) {
22 + // no-op
23 +};
24 +
25 +// simulate the readable thing closing after a bit
26 +writable.once("finish", function() {
27 + setTimeout(function() {
28 + readable.push(null);
29 + }, 500);
30 +});
31 +
32 +var duplex = duplexer3(writable, readable);
33 +
34 +duplex.on("data", function(e) {
35 + console.log("got data", JSON.stringify(e));
36 +});
37 +
38 +duplex.on("finish", function() {
39 + console.log("got finish event");
40 +});
41 +
42 +duplex.on("end", function() {
43 + console.log("got end event");
44 +});
45 +
46 +duplex.write("oh, hi there", function() {
47 + console.log("finished writing");
48 +});
49 +
50 +duplex.end(function() {
51 + console.log("finished ending");
52 +});
53 +```
54 +
55 +```
56 +got data "oh, hi there"
57 +finished writing
58 +got finish event
59 +finished ending
60 +got end event
61 +```
62 +
63 +## Overview
64 +
65 +This is a reimplementation of [duplexer](https://www.npmjs.com/package/duplexer) using the
66 +Streams3 API which is standard in Node as of v4. Everything largely
67 +works the same.
68 +
69 +
70 +
71 +## Installation
72 +
73 +[Available via `npm`](https://docs.npmjs.com/cli/install):
74 +
75 +```
76 +$ npm i duplexer3
77 +```
78 +
79 +## API
80 +
81 +### duplexer3
82 +
83 +Creates a new `DuplexWrapper` object, which is the actual class that implements
84 +most of the fun stuff. All that fun stuff is hidden. DON'T LOOK.
85 +
86 +```javascript
87 +duplexer3([options], writable, readable)
88 +```
89 +
90 +```javascript
91 +const duplex = duplexer3(new stream.Writable(), new stream.Readable());
92 +```
93 +
94 +Arguments
95 +
96 +* __options__ - an object specifying the regular `stream.Duplex` options, as
97 + well as the properties described below.
98 +* __writable__ - a writable stream
99 +* __readable__ - a readable stream
100 +
101 +Options
102 +
103 +* __bubbleErrors__ - a boolean value that specifies whether to bubble errors
104 + from the underlying readable/writable streams. Default is `true`.
105 +
106 +
107 +## License
108 +
109 +3-clause BSD. [A copy](./LICENSE) is included with the source.
110 +
111 +## Contact
112 +
113 +* GitHub ([deoxxa](http://github.com/deoxxa))
114 +* Twitter ([@deoxxa](http://twitter.com/deoxxa))
115 +* Email ([deoxxa@fknsrs.biz](mailto:deoxxa@fknsrs.biz))
1 +"use strict";
2 +
3 +var stream = require("stream");
4 +
5 +function DuplexWrapper(options, writable, readable) {
6 + if (typeof readable === "undefined") {
7 + readable = writable;
8 + writable = options;
9 + options = null;
10 + }
11 +
12 + stream.Duplex.call(this, options);
13 +
14 + if (typeof readable.read !== "function") {
15 + readable = (new stream.Readable(options)).wrap(readable);
16 + }
17 +
18 + this._writable = writable;
19 + this._readable = readable;
20 + this._waiting = false;
21 +
22 + var self = this;
23 +
24 + writable.once("finish", function() {
25 + self.end();
26 + });
27 +
28 + this.once("finish", function() {
29 + writable.end();
30 + });
31 +
32 + readable.on("readable", function() {
33 + if (self._waiting) {
34 + self._waiting = false;
35 + self._read();
36 + }
37 + });
38 +
39 + readable.once("end", function() {
40 + self.push(null);
41 + });
42 +
43 + if (!options || typeof options.bubbleErrors === "undefined" || options.bubbleErrors) {
44 + writable.on("error", function(err) {
45 + self.emit("error", err);
46 + });
47 +
48 + readable.on("error", function(err) {
49 + self.emit("error", err);
50 + });
51 + }
52 +}
53 +
54 +DuplexWrapper.prototype = Object.create(stream.Duplex.prototype, {constructor: {value: DuplexWrapper}});
55 +
56 +DuplexWrapper.prototype._write = function _write(input, encoding, done) {
57 + this._writable.write(input, encoding, done);
58 +};
59 +
60 +DuplexWrapper.prototype._read = function _read() {
61 + var buf;
62 + var reads = 0;
63 + while ((buf = this._readable.read()) !== null) {
64 + this.push(buf);
65 + reads++;
66 + }
67 + if (reads === 0) {
68 + this._waiting = true;
69 + }
70 +};
71 +
72 +module.exports = function duplex2(options, writable, readable) {
73 + return new DuplexWrapper(options, writable, readable);
74 +};
75 +
76 +module.exports.DuplexWrapper = DuplexWrapper;
1 +{
2 + "name": "duplexer3",
3 + "version": "0.1.4",
4 + "description": "Like duplexer but using streams3",
5 + "engine": {
6 + "node": ">=4"
7 + },
8 + "files": [
9 + "index.js"
10 + ],
11 + "scripts": {
12 + "test": "mocha -R tap"
13 + },
14 + "repository": "floatdrop/duplexer3",
15 + "keywords": [
16 + "duplex",
17 + "duplexer",
18 + "stream",
19 + "stream3",
20 + "join",
21 + "combine"
22 + ],
23 + "author": "Conrad Pankoff <deoxxa@fknsrs.biz> (http://www.fknsrs.biz/)",
24 + "license": "BSD-3-Clause",
25 + "devDependencies": {
26 + "mocha": "^2.2.5"
27 + }
28 +}
1 +The MIT License (MIT)
2 +
3 +Copyright (c) 2014 Arnout Kazemier
4 +
5 +Permission is hereby granted, free of charge, to any person obtaining a copy
6 +of this software and associated documentation files (the "Software"), to deal
7 +in the Software without restriction, including without limitation the rights
8 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 +copies of the Software, and to permit persons to whom the Software is
10 +furnished to do so, subject to the following conditions:
11 +
12 +The above copyright notice and this permission notice shall be included in all
13 +copies or substantial portions of the Software.
14 +
15 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 +SOFTWARE.
1 +# EventEmitter3
2 +
3 +[![Version npm](https://img.shields.io/npm/v/eventemitter3.svg?style=flat-square)](http://browsenpm.org/package/eventemitter3)[![Build Status](https://img.shields.io/travis/primus/eventemitter3/master.svg?style=flat-square)](https://travis-ci.org/primus/eventemitter3)[![Dependencies](https://img.shields.io/david/primus/eventemitter3.svg?style=flat-square)](https://david-dm.org/primus/eventemitter3)[![Coverage Status](https://img.shields.io/coveralls/primus/eventemitter3/master.svg?style=flat-square)](https://coveralls.io/r/primus/eventemitter3?branch=master)[![IRC channel](https://img.shields.io/badge/IRC-irc.freenode.net%23primus-00a8ff.svg?style=flat-square)](https://webchat.freenode.net/?channels=primus)
4 +
5 +[![Sauce Test Status](https://saucelabs.com/browser-matrix/eventemitter3.svg)](https://saucelabs.com/u/eventemitter3)
6 +
7 +EventEmitter3 is a high performance EventEmitter. It has been micro-optimized
8 +for various of code paths making this, one of, if not the fastest EventEmitter
9 +available for Node.js and browsers. The module is API compatible with the
10 +EventEmitter that ships by default with Node.js but there are some slight
11 +differences:
12 +
13 +- Domain support has been removed.
14 +- We do not `throw` an error when you emit an `error` event and nobody is
15 + listening.
16 +- The `newListener` event is removed as the use-cases for this functionality are
17 + really just edge cases.
18 +- No `setMaxListeners` and it's pointless memory leak warnings. If you want to
19 + add `end` listeners you should be able to do that without modules complaining.
20 +- No `listenerCount` function. Use `EE.listeners(event).length` instead.
21 +- Support for custom context for events so there is no need to use `fn.bind`.
22 +- `listeners` method can do existence checking instead of returning only arrays.
23 +
24 +It's a drop in replacement for existing EventEmitters, but just faster. Free
25 +performance, who wouldn't want that? The EventEmitter is written in EcmaScript 3
26 +so it will work in the oldest browsers and node versions that you need to
27 +support.
28 +
29 +## Installation
30 +
31 +```bash
32 +$ npm install --save eventemitter3 # npm
33 +$ component install primus/eventemitter3 # Component
34 +$ bower install eventemitter3 # Bower
35 +```
36 +
37 +## Usage
38 +
39 +After installation the only thing you need to do is require the module:
40 +
41 +```js
42 +var EventEmitter = require('eventemitter3');
43 +```
44 +
45 +And you're ready to create your own EventEmitter instances. For the API
46 +documentation, please follow the official Node.js documentation:
47 +
48 +http://nodejs.org/api/events.html
49 +
50 +### Contextual emits
51 +
52 +We've upgraded the API of the `EventEmitter.on`, `EventEmitter.once` and
53 +`EventEmitter.removeListener` to accept an extra argument which is the `context`
54 +or `this` value that should be set for the emitted events. This means you no
55 +longer have the overhead of an event that required `fn.bind` in order to get a
56 +custom `this` value.
57 +
58 +```js
59 +var EE = new EventEmitter()
60 + , context = { foo: 'bar' };
61 +
62 +function emitted() {
63 + console.log(this === context); // true
64 +}
65 +
66 +EE.once('event-name', emitted, context);
67 +EE.on('another-event', emitted, context);
68 +EE.removeListener('another-event', emitted, context);
69 +```
70 +
71 +### Existence
72 +
73 +To check if there is already a listener for a given event you can supply the
74 +`listeners` method with an extra boolean argument. This will transform the
75 +output from an array, to a boolean value which indicates if there are listeners
76 +in place for the given event:
77 +
78 +```js
79 +var EE = new EventEmitter();
80 +EE.once('event-name', function () {});
81 +EE.on('another-event', function () {});
82 +
83 +EE.listeners('event-name', true); // returns true
84 +EE.listeners('unknown-name', true); // returns false
85 +```
86 +
87 +## License
88 +
89 +[MIT](LICENSE)
1 +'use strict';
2 +
3 +var has = Object.prototype.hasOwnProperty;
4 +
5 +//
6 +// We store our EE objects in a plain object whose properties are event names.
7 +// If `Object.create(null)` is not supported we prefix the event names with a
8 +// `~` to make sure that the built-in object properties are not overridden or
9 +// used as an attack vector.
10 +// We also assume that `Object.create(null)` is available when the event name
11 +// is an ES6 Symbol.
12 +//
13 +var prefix = typeof Object.create !== 'function' ? '~' : false;
14 +
15 +/**
16 + * Representation of a single EventEmitter function.
17 + *
18 + * @param {Function} fn Event handler to be called.
19 + * @param {Mixed} context Context for function execution.
20 + * @param {Boolean} [once=false] Only emit once
21 + * @api private
22 + */
23 +function EE(fn, context, once) {
24 + this.fn = fn;
25 + this.context = context;
26 + this.once = once || false;
27 +}
28 +
29 +/**
30 + * Minimal EventEmitter interface that is molded against the Node.js
31 + * EventEmitter interface.
32 + *
33 + * @constructor
34 + * @api public
35 + */
36 +function EventEmitter() { /* Nothing to set */ }
37 +
38 +/**
39 + * Hold the assigned EventEmitters by name.
40 + *
41 + * @type {Object}
42 + * @private
43 + */
44 +EventEmitter.prototype._events = undefined;
45 +
46 +/**
47 + * Return an array listing the events for which the emitter has registered
48 + * listeners.
49 + *
50 + * @returns {Array}
51 + * @api public
52 + */
53 +EventEmitter.prototype.eventNames = function eventNames() {
54 + var events = this._events
55 + , names = []
56 + , name;
57 +
58 + if (!events) return names;
59 +
60 + for (name in events) {
61 + if (has.call(events, name)) names.push(prefix ? name.slice(1) : name);
62 + }
63 +
64 + if (Object.getOwnPropertySymbols) {
65 + return names.concat(Object.getOwnPropertySymbols(events));
66 + }
67 +
68 + return names;
69 +};
70 +
71 +/**
72 + * Return a list of assigned event listeners.
73 + *
74 + * @param {String} event The events that should be listed.
75 + * @param {Boolean} exists We only need to know if there are listeners.
76 + * @returns {Array|Boolean}
77 + * @api public
78 + */
79 +EventEmitter.prototype.listeners = function listeners(event, exists) {
80 + var evt = prefix ? prefix + event : event
81 + , available = this._events && this._events[evt];
82 +
83 + if (exists) return !!available;
84 + if (!available) return [];
85 + if (available.fn) return [available.fn];
86 +
87 + for (var i = 0, l = available.length, ee = new Array(l); i < l; i++) {
88 + ee[i] = available[i].fn;
89 + }
90 +
91 + return ee;
92 +};
93 +
94 +/**
95 + * Emit an event to all registered event listeners.
96 + *
97 + * @param {String} event The name of the event.
98 + * @returns {Boolean} Indication if we've emitted an event.
99 + * @api public
100 + */
101 +EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) {
102 + var evt = prefix ? prefix + event : event;
103 +
104 + if (!this._events || !this._events[evt]) return false;
105 +
106 + var listeners = this._events[evt]
107 + , len = arguments.length
108 + , args
109 + , i;
110 +
111 + if ('function' === typeof listeners.fn) {
112 + if (listeners.once) this.removeListener(event, listeners.fn, undefined, true);
113 +
114 + switch (len) {
115 + case 1: return listeners.fn.call(listeners.context), true;
116 + case 2: return listeners.fn.call(listeners.context, a1), true;
117 + case 3: return listeners.fn.call(listeners.context, a1, a2), true;
118 + case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true;
119 + case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true;
120 + case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true;
121 + }
122 +
123 + for (i = 1, args = new Array(len -1); i < len; i++) {
124 + args[i - 1] = arguments[i];
125 + }
126 +
127 + listeners.fn.apply(listeners.context, args);
128 + } else {
129 + var length = listeners.length
130 + , j;
131 +
132 + for (i = 0; i < length; i++) {
133 + if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true);
134 +
135 + switch (len) {
136 + case 1: listeners[i].fn.call(listeners[i].context); break;
137 + case 2: listeners[i].fn.call(listeners[i].context, a1); break;
138 + case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break;
139 + default:
140 + if (!args) for (j = 1, args = new Array(len -1); j < len; j++) {
141 + args[j - 1] = arguments[j];
142 + }
143 +
144 + listeners[i].fn.apply(listeners[i].context, args);
145 + }
146 + }
147 + }
148 +
149 + return true;
150 +};
151 +
152 +/**
153 + * Register a new EventListener for the given event.
154 + *
155 + * @param {String} event Name of the event.
156 + * @param {Function} fn Callback function.
157 + * @param {Mixed} [context=this] The context of the function.
158 + * @api public
159 + */
160 +EventEmitter.prototype.on = function on(event, fn, context) {
161 + var listener = new EE(fn, context || this)
162 + , evt = prefix ? prefix + event : event;
163 +
164 + if (!this._events) this._events = prefix ? {} : Object.create(null);
165 + if (!this._events[evt]) this._events[evt] = listener;
166 + else {
167 + if (!this._events[evt].fn) this._events[evt].push(listener);
168 + else this._events[evt] = [
169 + this._events[evt], listener
170 + ];
171 + }
172 +
173 + return this;
174 +};
175 +
176 +/**
177 + * Add an EventListener that's only called once.
178 + *
179 + * @param {String} event Name of the event.
180 + * @param {Function} fn Callback function.
181 + * @param {Mixed} [context=this] The context of the function.
182 + * @api public
183 + */
184 +EventEmitter.prototype.once = function once(event, fn, context) {
185 + var listener = new EE(fn, context || this, true)
186 + , evt = prefix ? prefix + event : event;
187 +
188 + if (!this._events) this._events = prefix ? {} : Object.create(null);
189 + if (!this._events[evt]) this._events[evt] = listener;
190 + else {
191 + if (!this._events[evt].fn) this._events[evt].push(listener);
192 + else this._events[evt] = [
193 + this._events[evt], listener
194 + ];
195 + }
196 +
197 + return this;
198 +};
199 +
200 +/**
201 + * Remove event listeners.
202 + *
203 + * @param {String} event The event we want to remove.
204 + * @param {Function} fn The listener that we need to find.
205 + * @param {Mixed} context Only remove listeners matching this context.
206 + * @param {Boolean} once Only remove once listeners.
207 + * @api public
208 + */
209 +EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) {
210 + var evt = prefix ? prefix + event : event;
211 +
212 + if (!this._events || !this._events[evt]) return this;
213 +
214 + var listeners = this._events[evt]
215 + , events = [];
216 +
217 + if (fn) {
218 + if (listeners.fn) {
219 + if (
220 + listeners.fn !== fn
221 + || (once && !listeners.once)
222 + || (context && listeners.context !== context)
223 + ) {
224 + events.push(listeners);
225 + }
226 + } else {
227 + for (var i = 0, length = listeners.length; i < length; i++) {
228 + if (
229 + listeners[i].fn !== fn
230 + || (once && !listeners[i].once)
231 + || (context && listeners[i].context !== context)
232 + ) {
233 + events.push(listeners[i]);
234 + }
235 + }
236 + }
237 + }
238 +
239 + //
240 + // Reset the array, or remove it completely if we have no more listeners.
241 + //
242 + if (events.length) {
243 + this._events[evt] = events.length === 1 ? events[0] : events;
244 + } else {
245 + delete this._events[evt];
246 + }
247 +
248 + return this;
249 +};
250 +
251 +/**
252 + * Remove all listeners or only the listeners for the specified event.
253 + *
254 + * @param {String} event The event want to remove all listeners for.
255 + * @api public
256 + */
257 +EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) {
258 + if (!this._events) return this;
259 +
260 + if (event) delete this._events[prefix ? prefix + event : event];
261 + else this._events = prefix ? {} : Object.create(null);
262 +
263 + return this;
264 +};
265 +
266 +//
267 +// Alias methods names because people roll like that.
268 +//
269 +EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
270 +EventEmitter.prototype.addListener = EventEmitter.prototype.on;
271 +
272 +//
273 +// This function doesn't apply anymore.
274 +//
275 +EventEmitter.prototype.setMaxListeners = function setMaxListeners() {
276 + return this;
277 +};
278 +
279 +//
280 +// Expose the prefix.
281 +//
282 +EventEmitter.prefixed = prefix;
283 +
284 +//
285 +// Expose the module.
286 +//
287 +if ('undefined' !== typeof module) {
288 + module.exports = EventEmitter;
289 +}
1 +{
2 + "name": "eventemitter3",
3 + "version": "1.2.0",
4 + "description": "EventEmitter3 focuses on performance while maintaining a Node.js AND browser compatible interface.",
5 + "main": "index.js",
6 + "scripts": {
7 + "test-node": "istanbul cover _mocha --report lcovonly -- test.js",
8 + "coverage": "istanbul cover _mocha -- test.js",
9 + "test-browser": "zuul -- test.js",
10 + "sync": "node versions.js",
11 + "test": "mocha test.js"
12 + },
13 + "repository": {
14 + "type": "git",
15 + "url": "git://github.com/primus/eventemitter3.git"
16 + },
17 + "keywords": [
18 + "EventEmitter",
19 + "EventEmitter2",
20 + "EventEmitter3",
21 + "Events",
22 + "addEventListener",
23 + "addListener",
24 + "emit",
25 + "emits",
26 + "emitter",
27 + "event",
28 + "once",
29 + "pub/sub",
30 + "publish",
31 + "reactor",
32 + "subscribe"
33 + ],
34 + "author": "Arnout Kazemier",
35 + "license": "MIT",
36 + "bugs": {
37 + "url": "https://github.com/primus/eventemitter3/issues"
38 + },
39 + "pre-commit": "sync, test",
40 + "devDependencies": {
41 + "assume": "1.3.x",
42 + "istanbul": "0.4.x",
43 + "mocha": "2.4.x",
44 + "pre-commit": "1.1.x",
45 + "zuul": "3.10.x"
46 + }
47 +}
1 +'use strict';
2 +const PassThrough = require('stream').PassThrough;
3 +
4 +module.exports = opts => {
5 + opts = Object.assign({}, opts);
6 +
7 + const array = opts.array;
8 + let encoding = opts.encoding;
9 + const buffer = encoding === 'buffer';
10 + let objectMode = false;
11 +
12 + if (array) {
13 + objectMode = !(encoding || buffer);
14 + } else {
15 + encoding = encoding || 'utf8';
16 + }
17 +
18 + if (buffer) {
19 + encoding = null;
20 + }
21 +
22 + let len = 0;
23 + const ret = [];
24 + const stream = new PassThrough({objectMode});
25 +
26 + if (encoding) {
27 + stream.setEncoding(encoding);
28 + }
29 +
30 + stream.on('data', chunk => {
31 + ret.push(chunk);
32 +
33 + if (objectMode) {
34 + len = ret.length;
35 + } else {
36 + len += chunk.length;
37 + }
38 + });
39 +
40 + stream.getBufferedValue = () => {
41 + if (array) {
42 + return ret;
43 + }
44 +
45 + return buffer ? Buffer.concat(ret, len) : ret.join('');
46 + };
47 +
48 + stream.getBufferedLength = () => len;
49 +
50 + return stream;
51 +};
1 +'use strict';
2 +const bufferStream = require('./buffer-stream');
3 +
4 +function getStream(inputStream, opts) {
5 + if (!inputStream) {
6 + return Promise.reject(new Error('Expected a stream'));
7 + }
8 +
9 + opts = Object.assign({maxBuffer: Infinity}, opts);
10 +
11 + const maxBuffer = opts.maxBuffer;
12 + let stream;
13 + let clean;
14 +
15 + const p = new Promise((resolve, reject) => {
16 + const error = err => {
17 + if (err) { // null check
18 + err.bufferedData = stream.getBufferedValue();
19 + }
20 +
21 + reject(err);
22 + };
23 +
24 + stream = bufferStream(opts);
25 + inputStream.once('error', error);
26 + inputStream.pipe(stream);
27 +
28 + stream.on('data', () => {
29 + if (stream.getBufferedLength() > maxBuffer) {
30 + reject(new Error('maxBuffer exceeded'));
31 + }
32 + });
33 + stream.once('error', error);
34 + stream.on('end', resolve);
35 +
36 + clean = () => {
37 + // some streams doesn't implement the `stream.Readable` interface correctly
38 + if (inputStream.unpipe) {
39 + inputStream.unpipe(stream);
40 + }
41 + };
42 + });
43 +
44 + p.then(clean, clean);
45 +
46 + return p.then(() => stream.getBufferedValue());
47 +}
48 +
49 +module.exports = getStream;
50 +module.exports.buffer = (stream, opts) => getStream(stream, Object.assign({}, opts, {encoding: 'buffer'}));
51 +module.exports.array = (stream, opts) => getStream(stream, Object.assign({}, opts, {array: true}));
1 +The MIT License (MIT)
2 +
3 +Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
4 +
5 +Permission is hereby granted, free of charge, to any person obtaining a copy
6 +of this software and associated documentation files (the "Software"), to deal
7 +in the Software without restriction, including without limitation the rights
8 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 +copies of the Software, and to permit persons to whom the Software is
10 +furnished to do so, subject to the following conditions:
11 +
12 +The above copyright notice and this permission notice shall be included in
13 +all copies or substantial portions of the Software.
14 +
15 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 +THE SOFTWARE.
1 +{
2 + "name": "get-stream",
3 + "version": "3.0.0",
4 + "description": "Get a stream as a string, buffer, or array",
5 + "license": "MIT",
6 + "repository": "sindresorhus/get-stream",
7 + "author": {
8 + "name": "Sindre Sorhus",
9 + "email": "sindresorhus@gmail.com",
10 + "url": "sindresorhus.com"
11 + },
12 + "engines": {
13 + "node": ">=4"
14 + },
15 + "scripts": {
16 + "test": "xo && ava"
17 + },
18 + "files": [
19 + "index.js",
20 + "buffer-stream.js"
21 + ],
22 + "keywords": [
23 + "get",
24 + "stream",
25 + "promise",
26 + "concat",
27 + "string",
28 + "str",
29 + "text",
30 + "buffer",
31 + "read",
32 + "data",
33 + "consume",
34 + "readable",
35 + "readablestream",
36 + "array",
37 + "object",
38 + "obj"
39 + ],
40 + "devDependencies": {
41 + "ava": "*",
42 + "into-stream": "^3.0.0",
43 + "xo": "*"
44 + },
45 + "xo": {
46 + "esnext": true
47 + }
48 +}
1 +# get-stream [![Build Status](https://travis-ci.org/sindresorhus/get-stream.svg?branch=master)](https://travis-ci.org/sindresorhus/get-stream)
2 +
3 +> Get a stream as a string, buffer, or array
4 +
5 +
6 +## Install
7 +
8 +```
9 +$ npm install --save get-stream
10 +```
11 +
12 +
13 +## Usage
14 +
15 +```js
16 +const fs = require('fs');
17 +const getStream = require('get-stream');
18 +const stream = fs.createReadStream('unicorn.txt');
19 +
20 +getStream(stream).then(str => {
21 + console.log(str);
22 + /*
23 + ,,))))))));,
24 + __)))))))))))))),
25 + \|/ -\(((((''''((((((((.
26 + -*-==//////(('' . `)))))),
27 + /|\ ))| o ;-. '((((( ,(,
28 + ( `| / ) ;))))' ,_))^;(~
29 + | | | ,))((((_ _____------~~~-. %,;(;(>';'~
30 + o_); ; )))(((` ~---~ `:: \ %%~~)(v;(`('~
31 + ; ''''```` `: `:::|\,__,%% );`'; ~
32 + | _ ) / `:|`----' `-'
33 + ______/\/~ | / /
34 + /~;;.____/;;' / ___--,-( `;;;/
35 + / // _;______;'------~~~~~ /;;/\ /
36 + // | | / ; \;;,\
37 + (<_ | ; /',/-----' _>
38 + \_| ||_ //~;~~~~~~~~~
39 + `\_| (,~~
40 + \~\
41 + ~~
42 + */
43 +});
44 +```
45 +
46 +
47 +## API
48 +
49 +The methods returns a promise that resolves when the `end` event fires on the stream, indicating that there is no more data to be read. The stream is switched to flowing mode.
50 +
51 +### getStream(stream, [options])
52 +
53 +Get the `stream` as a string.
54 +
55 +#### options
56 +
57 +##### encoding
58 +
59 +Type: `string`<br>
60 +Default: `utf8`
61 +
62 +[Encoding](https://nodejs.org/api/buffer.html#buffer_buffer) of the incoming stream.
63 +
64 +##### maxBuffer
65 +
66 +Type: `number`<br>
67 +Default: `Infinity`
68 +
69 +Maximum length of the returned string. If it exceeds this value before the stream ends, the promise will be rejected.
70 +
71 +### getStream.buffer(stream, [options])
72 +
73 +Get the `stream` as a buffer.
74 +
75 +It honors the `maxBuffer` option as above, but it refers to byte length rather than string length.
76 +
77 +### getStream.array(stream, [options])
78 +
79 +Get the `stream` as an array of values.
80 +
81 +It honors both the `maxBuffer` and `encoding` options. The behavior changes slightly based on the encoding chosen:
82 +
83 +- When `encoding` is unset, it assumes an [object mode stream](https://nodesource.com/blog/understanding-object-streams/) and collects values emitted from `stream` unmodified. In this case `maxBuffer` refers to the number of items in the array (not the sum of their sizes).
84 +
85 +- When `encoding` is set to `buffer`, it collects an array of buffers. `maxBuffer` refers to the summed byte lengths of every buffer in the array.
86 +
87 +- When `encoding` is set to anything else, it collects an array of strings. `maxBuffer` refers to the summed character lengths of every string in the array.
88 +
89 +
90 +## Errors
91 +
92 +If the input stream emits an `error` event, the promise will be rejected with the error. The buffered data will be attached to the `bufferedData` property of the error.
93 +
94 +```js
95 +getStream(streamThatErrorsAtTheEnd('unicorn'))
96 + .catch(err => {
97 + console.log(err.bufferedData);
98 + //=> 'unicorn'
99 + });
100 +```
101 +
102 +
103 +## FAQ
104 +
105 +### How is this different from [`concat-stream`](https://github.com/maxogden/concat-stream)?
106 +
107 +This module accepts a stream instead of being one and returns a promise instead of using a callback. The API is simpler and it only supports returning a string, buffer, or array. It doesn't have a fragile type inference. You explicitly choose what you want. And it doesn't depend on the huge `readable-stream` package.
108 +
109 +
110 +## Related
111 +
112 +- [get-stdin](https://github.com/sindresorhus/get-stdin) - Get stdin as a string or buffer
113 +
114 +
115 +## License
116 +
117 +MIT © [Sindre Sorhus](https://sindresorhus.com)
1 +'use strict';
2 +const EventEmitter = require('events');
3 +const http = require('http');
4 +const https = require('https');
5 +const PassThrough = require('stream').PassThrough;
6 +const urlLib = require('url');
7 +const querystring = require('querystring');
8 +const duplexer3 = require('duplexer3');
9 +const isStream = require('is-stream');
10 +const getStream = require('get-stream');
11 +const timedOut = require('timed-out');
12 +const urlParseLax = require('url-parse-lax');
13 +const lowercaseKeys = require('lowercase-keys');
14 +const isRedirect = require('is-redirect');
15 +const unzipResponse = require('unzip-response');
16 +const createErrorClass = require('create-error-class');
17 +const isRetryAllowed = require('is-retry-allowed');
18 +const Buffer = require('safe-buffer').Buffer;
19 +const pkg = require('./package');
20 +
21 +function requestAsEventEmitter(opts) {
22 + opts = opts || {};
23 +
24 + const ee = new EventEmitter();
25 + const requestUrl = opts.href || urlLib.resolve(urlLib.format(opts), opts.path);
26 + let redirectCount = 0;
27 + let retryCount = 0;
28 + let redirectUrl;
29 +
30 + const get = opts => {
31 + const fn = opts.protocol === 'https:' ? https : http;
32 +
33 + const req = fn.request(opts, res => {
34 + const statusCode = res.statusCode;
35 +
36 + if (isRedirect(statusCode) && opts.followRedirect && 'location' in res.headers && (opts.method === 'GET' || opts.method === 'HEAD')) {
37 + res.resume();
38 +
39 + if (++redirectCount > 10) {
40 + ee.emit('error', new got.MaxRedirectsError(statusCode, opts), null, res);
41 + return;
42 + }
43 +
44 + const bufferString = Buffer.from(res.headers.location, 'binary').toString();
45 +
46 + redirectUrl = urlLib.resolve(urlLib.format(opts), bufferString);
47 + const redirectOpts = Object.assign({}, opts, urlLib.parse(redirectUrl));
48 +
49 + ee.emit('redirect', res, redirectOpts);
50 +
51 + get(redirectOpts);
52 +
53 + return;
54 + }
55 +
56 + setImmediate(() => {
57 + const response = typeof unzipResponse === 'function' && req.method !== 'HEAD' ? unzipResponse(res) : res;
58 + response.url = redirectUrl || requestUrl;
59 + response.requestUrl = requestUrl;
60 +
61 + ee.emit('response', response);
62 + });
63 + });
64 +
65 + req.once('error', err => {
66 + const backoff = opts.retries(++retryCount, err);
67 +
68 + if (backoff) {
69 + setTimeout(get, backoff, opts);
70 + return;
71 + }
72 +
73 + ee.emit('error', new got.RequestError(err, opts));
74 + });
75 +
76 + if (opts.gotTimeout) {
77 + timedOut(req, opts.gotTimeout);
78 + }
79 +
80 + setImmediate(() => {
81 + ee.emit('request', req);
82 + });
83 + };
84 +
85 + get(opts);
86 + return ee;
87 +}
88 +
89 +function asPromise(opts) {
90 + return new Promise((resolve, reject) => {
91 + const ee = requestAsEventEmitter(opts);
92 +
93 + ee.on('request', req => {
94 + if (isStream(opts.body)) {
95 + opts.body.pipe(req);
96 + opts.body = undefined;
97 + return;
98 + }
99 +
100 + req.end(opts.body);
101 + });
102 +
103 + ee.on('response', res => {
104 + const stream = opts.encoding === null ? getStream.buffer(res) : getStream(res, opts);
105 +
106 + stream
107 + .catch(err => reject(new got.ReadError(err, opts)))
108 + .then(data => {
109 + const statusCode = res.statusCode;
110 + const limitStatusCode = opts.followRedirect ? 299 : 399;
111 +
112 + res.body = data;
113 +
114 + if (opts.json && res.body) {
115 + try {
116 + res.body = JSON.parse(res.body);
117 + } catch (e) {
118 + throw new got.ParseError(e, statusCode, opts, data);
119 + }
120 + }
121 +
122 + if (statusCode < 200 || statusCode > limitStatusCode) {
123 + throw new got.HTTPError(statusCode, opts);
124 + }
125 +
126 + resolve(res);
127 + })
128 + .catch(err => {
129 + Object.defineProperty(err, 'response', {value: res});
130 + reject(err);
131 + });
132 + });
133 +
134 + ee.on('error', reject);
135 + });
136 +}
137 +
138 +function asStream(opts) {
139 + const input = new PassThrough();
140 + const output = new PassThrough();
141 + const proxy = duplexer3(input, output);
142 +
143 + if (opts.json) {
144 + throw new Error('got can not be used as stream when options.json is used');
145 + }
146 +
147 + if (opts.body) {
148 + proxy.write = () => {
149 + throw new Error('got\'s stream is not writable when options.body is used');
150 + };
151 + }
152 +
153 + const ee = requestAsEventEmitter(opts);
154 +
155 + ee.on('request', req => {
156 + proxy.emit('request', req);
157 +
158 + if (isStream(opts.body)) {
159 + opts.body.pipe(req);
160 + return;
161 + }
162 +
163 + if (opts.body) {
164 + req.end(opts.body);
165 + return;
166 + }
167 +
168 + if (opts.method === 'POST' || opts.method === 'PUT' || opts.method === 'PATCH') {
169 + input.pipe(req);
170 + return;
171 + }
172 +
173 + req.end();
174 + });
175 +
176 + ee.on('response', res => {
177 + const statusCode = res.statusCode;
178 +
179 + res.pipe(output);
180 +
181 + if (statusCode < 200 || statusCode > 299) {
182 + proxy.emit('error', new got.HTTPError(statusCode, opts), null, res);
183 + return;
184 + }
185 +
186 + proxy.emit('response', res);
187 + });
188 +
189 + ee.on('redirect', proxy.emit.bind(proxy, 'redirect'));
190 + ee.on('error', proxy.emit.bind(proxy, 'error'));
191 +
192 + return proxy;
193 +}
194 +
195 +function normalizeArguments(url, opts) {
196 + if (typeof url !== 'string' && typeof url !== 'object') {
197 + throw new Error(`Parameter \`url\` must be a string or object, not ${typeof url}`);
198 + }
199 +
200 + if (typeof url === 'string') {
201 + url = url.replace(/^unix:/, 'http://$&');
202 + url = urlParseLax(url);
203 +
204 + if (url.auth) {
205 + throw new Error('Basic authentication must be done with auth option');
206 + }
207 + }
208 +
209 + opts = Object.assign(
210 + {
211 + protocol: 'http:',
212 + path: '',
213 + retries: 5
214 + },
215 + url,
216 + opts
217 + );
218 +
219 + opts.headers = Object.assign({
220 + 'user-agent': `${pkg.name}/${pkg.version} (https://github.com/sindresorhus/got)`,
221 + 'accept-encoding': 'gzip,deflate'
222 + }, lowercaseKeys(opts.headers));
223 +
224 + const query = opts.query;
225 +
226 + if (query) {
227 + if (typeof query !== 'string') {
228 + opts.query = querystring.stringify(query);
229 + }
230 +
231 + opts.path = `${opts.path.split('?')[0]}?${opts.query}`;
232 + delete opts.query;
233 + }
234 +
235 + if (opts.json && opts.headers.accept === undefined) {
236 + opts.headers.accept = 'application/json';
237 + }
238 +
239 + let body = opts.body;
240 +
241 + if (body) {
242 + if (typeof body !== 'string' && !(body !== null && typeof body === 'object')) {
243 + throw new Error('options.body must be a ReadableStream, string, Buffer or plain Object');
244 + }
245 +
246 + opts.method = opts.method || 'POST';
247 +
248 + if (isStream(body) && typeof body.getBoundary === 'function') {
249 + // Special case for https://github.com/form-data/form-data
250 + opts.headers['content-type'] = opts.headers['content-type'] || `multipart/form-data; boundary=${body.getBoundary()}`;
251 + } else if (body !== null && typeof body === 'object' && !Buffer.isBuffer(body) && !isStream(body)) {
252 + opts.headers['content-type'] = opts.headers['content-type'] || 'application/x-www-form-urlencoded';
253 + body = opts.body = querystring.stringify(body);
254 + }
255 +
256 + if (opts.headers['content-length'] === undefined && opts.headers['transfer-encoding'] === undefined && !isStream(body)) {
257 + const length = typeof body === 'string' ? Buffer.byteLength(body) : body.length;
258 + opts.headers['content-length'] = length;
259 + }
260 + }
261 +
262 + opts.method = (opts.method || 'GET').toUpperCase();
263 +
264 + if (opts.hostname === 'unix') {
265 + const matches = /(.+):(.+)/.exec(opts.path);
266 +
267 + if (matches) {
268 + opts.socketPath = matches[1];
269 + opts.path = matches[2];
270 + opts.host = null;
271 + }
272 + }
273 +
274 + if (typeof opts.retries !== 'function') {
275 + const retries = opts.retries;
276 +
277 + opts.retries = (iter, err) => {
278 + if (iter > retries || !isRetryAllowed(err)) {
279 + return 0;
280 + }
281 +
282 + const noise = Math.random() * 100;
283 +
284 + return ((1 << iter) * 1000) + noise;
285 + };
286 + }
287 +
288 + if (opts.followRedirect === undefined) {
289 + opts.followRedirect = true;
290 + }
291 +
292 + if (opts.timeout) {
293 + opts.gotTimeout = opts.timeout;
294 + delete opts.timeout;
295 + }
296 +
297 + return opts;
298 +}
299 +
300 +function got(url, opts) {
301 + try {
302 + return asPromise(normalizeArguments(url, opts));
303 + } catch (err) {
304 + return Promise.reject(err);
305 + }
306 +}
307 +
308 +const helpers = [
309 + 'get',
310 + 'post',
311 + 'put',
312 + 'patch',
313 + 'head',
314 + 'delete'
315 +];
316 +
317 +helpers.forEach(el => {
318 + got[el] = (url, opts) => got(url, Object.assign({}, opts, {method: el}));
319 +});
320 +
321 +got.stream = (url, opts) => asStream(normalizeArguments(url, opts));
322 +
323 +for (const el of helpers) {
324 + got.stream[el] = (url, opts) => got.stream(url, Object.assign({}, opts, {method: el}));
325 +}
326 +
327 +function stdError(error, opts) {
328 + if (error.code !== undefined) {
329 + this.code = error.code;
330 + }
331 +
332 + Object.assign(this, {
333 + message: error.message,
334 + host: opts.host,
335 + hostname: opts.hostname,
336 + method: opts.method,
337 + path: opts.path
338 + });
339 +}
340 +
341 +got.RequestError = createErrorClass('RequestError', stdError);
342 +got.ReadError = createErrorClass('ReadError', stdError);
343 +got.ParseError = createErrorClass('ParseError', function (e, statusCode, opts, data) {
344 + stdError.call(this, e, opts);
345 + this.statusCode = statusCode;
346 + this.statusMessage = http.STATUS_CODES[this.statusCode];
347 + this.message = `${e.message} in "${urlLib.format(opts)}": \n${data.slice(0, 77)}...`;
348 +});
349 +
350 +got.HTTPError = createErrorClass('HTTPError', function (statusCode, opts) {
351 + stdError.call(this, {}, opts);
352 + this.statusCode = statusCode;
353 + this.statusMessage = http.STATUS_CODES[this.statusCode];
354 + this.message = `Response code ${this.statusCode} (${this.statusMessage})`;
355 +});
356 +
357 +got.MaxRedirectsError = createErrorClass('MaxRedirectsError', function (statusCode, opts) {
358 + stdError.call(this, {}, opts);
359 + this.statusCode = statusCode;
360 + this.statusMessage = http.STATUS_CODES[this.statusCode];
361 + this.message = 'Redirected 10 times. Aborting.';
362 +});
363 +
364 +module.exports = got;
1 +The MIT License (MIT)
2 +
3 +Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
4 +
5 +Permission is hereby granted, free of charge, to any person obtaining a copy
6 +of this software and associated documentation files (the "Software"), to deal
7 +in the Software without restriction, including without limitation the rights
8 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 +copies of the Software, and to permit persons to whom the Software is
10 +furnished to do so, subject to the following conditions:
11 +
12 +The above copyright notice and this permission notice shall be included in
13 +all copies or substantial portions of the Software.
14 +
15 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 +THE SOFTWARE.
1 +{
2 + "name": "got",
3 + "version": "6.7.1",
4 + "description": "Simplified HTTP requests",
5 + "license": "MIT",
6 + "repository": "sindresorhus/got",
7 + "maintainers": [
8 + {
9 + "name": "Sindre Sorhus",
10 + "email": "sindresorhus@gmail.com",
11 + "url": "sindresorhus.com"
12 + },
13 + {
14 + "name": "Vsevolod Strukchinsky",
15 + "email": "floatdrop@gmail.com",
16 + "url": "github.com/floatdrop"
17 + }
18 + ],
19 + "engines": {
20 + "node": ">=4"
21 + },
22 + "browser": {
23 + "unzip-response": false
24 + },
25 + "scripts": {
26 + "test": "xo && nyc ava",
27 + "coveralls": "nyc report --reporter=text-lcov | coveralls"
28 + },
29 + "files": [
30 + "index.js"
31 + ],
32 + "keywords": [
33 + "http",
34 + "https",
35 + "get",
36 + "got",
37 + "url",
38 + "uri",
39 + "request",
40 + "util",
41 + "utility",
42 + "simple",
43 + "curl",
44 + "wget",
45 + "fetch"
46 + ],
47 + "dependencies": {
48 + "create-error-class": "^3.0.0",
49 + "duplexer3": "^0.1.4",
50 + "get-stream": "^3.0.0",
51 + "is-redirect": "^1.0.0",
52 + "is-retry-allowed": "^1.0.0",
53 + "is-stream": "^1.0.0",
54 + "lowercase-keys": "^1.0.0",
55 + "safe-buffer": "^5.0.1",
56 + "timed-out": "^4.0.0",
57 + "unzip-response": "^2.0.1",
58 + "url-parse-lax": "^1.0.0"
59 + },
60 + "devDependencies": {
61 + "ava": "^0.17.0",
62 + "coveralls": "^2.11.4",
63 + "form-data": "^2.1.1",
64 + "get-port": "^2.0.0",
65 + "into-stream": "^3.0.0",
66 + "nyc": "^10.0.0",
67 + "pem": "^1.4.4",
68 + "pify": "^2.3.0",
69 + "tempfile": "^1.1.1",
70 + "xo": "*"
71 + },
72 + "xo": {
73 + "esnext": true
74 + },
75 + "ava": {
76 + "concurrency": 4
77 + }
78 +}
1 +<h1 align="center">
2 + <br>
3 + <img width="360" src="https://rawgit.com/sindresorhus/got/master/media/logo.svg" alt="got">
4 + <br>
5 + <br>
6 + <br>
7 +</h1>
8 +
9 +> Simplified HTTP requests
10 +
11 +[![Build Status](https://travis-ci.org/sindresorhus/got.svg?branch=master)](https://travis-ci.org/sindresorhus/got) [![Coverage Status](https://coveralls.io/repos/github/sindresorhus/got/badge.svg?branch=master)](https://coveralls.io/github/sindresorhus/got?branch=master) [![Downloads](https://img.shields.io/npm/dm/got.svg)](https://npmjs.com/got)
12 +
13 +A nicer interface to the built-in [`http`](http://nodejs.org/api/http.html) module.
14 +
15 +It supports following redirects, promises, streams, retries, automagically handling gzip/deflate and some convenience options.
16 +
17 +Created because [`request`](https://github.com/request/request) is bloated *(several megabytes!)*.
18 +
19 +
20 +## Install
21 +
22 +**WARNING: Node.js 4 or higher is required for got@6 and above.** For older Node.js versions use [got@5](https://github.com/sindresorhus/got/tree/v5.x).
23 +
24 +```
25 +$ npm install --save got
26 +```
27 +
28 +
29 +## Usage
30 +
31 +```js
32 +const fs = require('fs');
33 +const got = require('got');
34 +
35 +got('todomvc.com')
36 + .then(response => {
37 + console.log(response.body);
38 + //=> '<!doctype html> ...'
39 + })
40 + .catch(error => {
41 + console.log(error.response.body);
42 + //=> 'Internal server error ...'
43 + });
44 +
45 +// Streams
46 +got.stream('todomvc.com').pipe(fs.createWriteStream('index.html'));
47 +
48 +// For POST, PUT and PATCH methods got.stream returns a WritableStream
49 +fs.createReadStream('index.html').pipe(got.stream.post('todomvc.com'));
50 +```
51 +
52 +
53 +### API
54 +
55 +It's a `GET` request by default, but can be changed in `options`.
56 +
57 +#### got(url, [options])
58 +
59 +Returns a Promise for a `response` object with a `body` property, a `url` property with the request URL or the final URL after redirects, and a `requestUrl` property with the original request URL.
60 +
61 +##### url
62 +
63 +Type: `string`, `object`
64 +
65 +The URL to request or a [`http.request` options](https://nodejs.org/api/http.html#http_http_request_options_callback) object.
66 +
67 +Properties from `options` will override properties in the parsed `url`.
68 +
69 +##### options
70 +
71 +Type: `object`
72 +
73 +Any of the [`http.request`](http://nodejs.org/api/http.html#http_http_request_options_callback) options.
74 +
75 +###### body
76 +
77 +Type: `string`, `buffer`, `readableStream`, `object`
78 +
79 +*This is mutually exclusive with stream mode.*
80 +
81 +Body that will be sent with a `POST` request.
82 +
83 +If present in `options` and `options.method` is not set, `options.method` will be set to `POST`.
84 +
85 +If `content-length` or `transfer-encoding` is not set in `options.headers` and `body` is a string or buffer, `content-length` will be set to the body length.
86 +
87 +If `body` is a plain object, it will be stringified with [`querystring.stringify`](https://nodejs.org/api/querystring.html#querystring_querystring_stringify_obj_sep_eq_options) and sent as `application/x-www-form-urlencoded`.
88 +
89 +###### encoding
90 +
91 +Type: `string`, `null`<br>
92 +Default: `'utf8'`
93 +
94 +Encoding to be used on `setEncoding` of the response data. If `null`, the body is returned as a Buffer.
95 +
96 +###### json
97 +
98 +Type: `boolean`<br>
99 +Default: `false`
100 +
101 +*This is mutually exclusive with stream mode.*
102 +
103 +Parse response body with `JSON.parse` and set `accept` header to `application/json`.
104 +
105 +###### query
106 +
107 +Type: `string`, `object`<br>
108 +
109 +Query string object that will be added to the request URL. This will override the query string in `url`.
110 +
111 +###### timeout
112 +
113 +Type: `number`, `object`
114 +
115 +Milliseconds to wait for a server to send response headers before aborting request with `ETIMEDOUT` error.
116 +
117 +Option accepts `object` with separate `connect` and `socket` fields for connection and socket inactivity timeouts.
118 +
119 +###### retries
120 +
121 +Type: `number`, `function`<br>
122 +Default: `5`
123 +
124 +Number of request retries when network errors happens. Delays between retries counts with function `1000 * Math.pow(2, retry) + Math.random() * 100`, where `retry` is attempt number (starts from 0).
125 +
126 +Option accepts `function` with `retry` and `error` arguments. Function must return delay in milliseconds (`0` return value cancels retry).
127 +
128 +**Note:** if `retries` is `number`, `ENOTFOUND` and `ENETUNREACH` error will not be retried (see full list in [`is-retry-allowed`](https://github.com/floatdrop/is-retry-allowed/blob/master/index.js#L12) module).
129 +
130 +###### followRedirect
131 +
132 +Type: `boolean`<br>
133 +Default: `true`
134 +
135 +Defines if redirect responses should be followed automatically.
136 +
137 +
138 +#### Streams
139 +
140 +#### got.stream(url, [options])
141 +
142 +`stream` method will return Duplex stream with additional events:
143 +
144 +##### .on('request', request)
145 +
146 +`request` event to get the request object of the request.
147 +
148 +**Tip**: You can use `request` event to abort request:
149 +
150 +```js
151 +got.stream('github.com')
152 + .on('request', req => setTimeout(() => req.abort(), 50));
153 +```
154 +
155 +##### .on('response', response)
156 +
157 +`response` event to get the response object of the final request.
158 +
159 +##### .on('redirect', response, nextOptions)
160 +
161 +`redirect` event to get the response object of a redirect. The second argument is options for the next request to the redirect location.
162 +
163 +##### .on('error', error, body, response)
164 +
165 +`error` event emitted in case of protocol error (like `ENOTFOUND` etc.) or status error (4xx or 5xx). The second argument is the body of the server response in case of status error. The third argument is response object.
166 +
167 +#### got.get(url, [options])
168 +#### got.post(url, [options])
169 +#### got.put(url, [options])
170 +#### got.patch(url, [options])
171 +#### got.head(url, [options])
172 +#### got.delete(url, [options])
173 +
174 +Sets `options.method` to the method name and makes a request.
175 +
176 +
177 +## Errors
178 +
179 +Each error contains (if available) `statusCode`, `statusMessage`, `host`, `hostname`, `method` and `path` properties to make debugging easier.
180 +
181 +In Promise mode, the `response` is attached to the error.
182 +
183 +#### got.RequestError
184 +
185 +When a request fails. Contains a `code` property with error class code, like `ECONNREFUSED`.
186 +
187 +#### got.ReadError
188 +
189 +When reading from response stream fails.
190 +
191 +#### got.ParseError
192 +
193 +When `json` option is enabled and `JSON.parse` fails.
194 +
195 +#### got.HTTPError
196 +
197 +When server response code is not 2xx. Contains `statusCode` and `statusMessage`.
198 +
199 +#### got.MaxRedirectsError
200 +
201 +When server redirects you more than 10 times.
202 +
203 +
204 +## Proxies
205 +
206 +You can use the [`tunnel`](https://github.com/koichik/node-tunnel) module with the `agent` option to work with proxies:
207 +
208 +```js
209 +const got = require('got');
210 +const tunnel = require('tunnel');
211 +
212 +got('todomvc.com', {
213 + agent: tunnel.httpOverHttp({
214 + proxy: {
215 + host: 'localhost'
216 + }
217 + })
218 +});
219 +```
220 +
221 +
222 +## Cookies
223 +
224 +You can use the [`cookie`](https://github.com/jshttp/cookie) module to include cookies in a request:
225 +
226 +```js
227 +const got = require('got');
228 +const cookie = require('cookie');
229 +
230 +got('google.com', {
231 + headers: {
232 + cookie: cookie.serialize('foo', 'bar')
233 + }
234 +});
235 +```
236 +
237 +
238 +## Form data
239 +
240 +You can use the [`form-data`](https://github.com/form-data/form-data) module to create POST request with form data:
241 +
242 +```js
243 +const fs = require('fs');
244 +const got = require('got');
245 +const FormData = require('form-data');
246 +const form = new FormData();
247 +
248 +form.append('my_file', fs.createReadStream('/foo/bar.jpg'));
249 +
250 +got.post('google.com', {
251 + body: form
252 +});
253 +```
254 +
255 +
256 +## OAuth
257 +
258 +You can use the [`oauth-1.0a`](https://github.com/ddo/oauth-1.0a) module to create a signed OAuth request:
259 +
260 +```js
261 +const got = require('got');
262 +const crypto = require('crypto');
263 +const OAuth = require('oauth-1.0a');
264 +
265 +const oauth = OAuth({
266 + consumer: {
267 + key: process.env.CONSUMER_KEY,
268 + secret: process.env.CONSUMER_SECRET
269 + },
270 + signature_method: 'HMAC-SHA1',
271 + hash_function: (baseString, key) => crypto.createHmac('sha1', key).update(baseString).digest('base64')
272 +});
273 +
274 +const token = {
275 + key: process.env.ACCESS_TOKEN,
276 + secret: process.env.ACCESS_TOKEN_SECRET
277 +};
278 +
279 +const url = 'https://api.twitter.com/1.1/statuses/home_timeline.json';
280 +
281 +got(url, {
282 + headers: oauth.toHeader(oauth.authorize({url, method: 'GET'}, token)),
283 + json: true
284 +});
285 +```
286 +
287 +
288 +## Unix Domain Sockets
289 +
290 +Requests can also be sent via [unix domain sockets](http://serverfault.com/questions/124517/whats-the-difference-between-unix-socket-and-tcp-ip-socket). Use the following URL scheme: `PROTOCOL://unix:SOCKET:PATH`.
291 +
292 +- `PROTOCOL` - `http` or `https` *(optional)*
293 +- `SOCKET` - absolute path to a unix domain socket, e.g. `/var/run/docker.sock`
294 +- `PATH` - request path, e.g. `/v2/keys`
295 +
296 +```js
297 +got('http://unix:/var/run/docker.sock:/containers/json');
298 +
299 +// or without protocol (http by default)
300 +got('unix:/var/run/docker.sock:/containers/json');
301 +```
302 +
303 +
304 +## Tip
305 +
306 +It's a good idea to set the `'user-agent'` header so the provider can more easily see how their resource is used. By default, it's the URL to this repo.
307 +
308 +```js
309 +const got = require('got');
310 +const pkg = require('./package.json');
311 +
312 +got('todomvc.com', {
313 + headers: {
314 + 'user-agent': `my-module/${pkg.version} (https://github.com/username/my-module)`
315 + }
316 +});
317 +```
318 +
319 +
320 +## Related
321 +
322 +- [gh-got](https://github.com/sindresorhus/gh-got) - Convenience wrapper for interacting with the GitHub API
323 +- [travis-got](https://github.com/samverschueren/travis-got) - Convenience wrapper for interacting with the Travis API
324 +
325 +
326 +## Created by
327 +
328 +[![Sindre Sorhus](https://avatars.githubusercontent.com/u/170270?v=3&s=100)](https://sindresorhus.com) | [![Vsevolod Strukchinsky](https://avatars.githubusercontent.com/u/365089?v=3&s=100)](https://github.com/floatdrop)
329 +---|---
330 +[Sindre Sorhus](https://sindresorhus.com) | [Vsevolod Strukchinsky](https://github.com/floatdrop)
331 +
332 +
333 +## License
334 +
335 +MIT © [Sindre Sorhus](https://sindresorhus.com)
1 +'use strict';
2 +module.exports = function (x) {
3 + if (typeof x !== 'number') {
4 + throw new TypeError('Expected a number');
5 + }
6 +
7 + return x === 300 ||
8 + x === 301 ||
9 + x === 302 ||
10 + x === 303 ||
11 + x === 305 ||
12 + x === 307 ||
13 + x === 308;
14 +};
1 +The MIT License (MIT)
2 +
3 +Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
4 +
5 +Permission is hereby granted, free of charge, to any person obtaining a copy
6 +of this software and associated documentation files (the "Software"), to deal
7 +in the Software without restriction, including without limitation the rights
8 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 +copies of the Software, and to permit persons to whom the Software is
10 +furnished to do so, subject to the following conditions:
11 +
12 +The above copyright notice and this permission notice shall be included in
13 +all copies or substantial portions of the Software.
14 +
15 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 +THE SOFTWARE.
1 +{
2 + "name": "is-redirect",
3 + "version": "1.0.0",
4 + "description": "Check if a number is a redirect HTTP status code",
5 + "license": "MIT",
6 + "repository": "sindresorhus/is-redirect",
7 + "author": {
8 + "name": "Sindre Sorhus",
9 + "email": "sindresorhus@gmail.com",
10 + "url": "sindresorhus.com"
11 + },
12 + "engines": {
13 + "node": ">=0.10.0"
14 + },
15 + "scripts": {
16 + "test": "node test.js"
17 + },
18 + "files": [
19 + "index.js"
20 + ],
21 + "keywords": [
22 + "redirect",
23 + "http",
24 + "https",
25 + "status",
26 + "code",
27 + "codes",
28 + "is",
29 + "check",
30 + "detect"
31 + ],
32 + "devDependencies": {
33 + "ava": "0.0.4"
34 + }
35 +}
1 +# is-redirect [![Build Status](https://travis-ci.org/sindresorhus/is-redirect.svg?branch=master)](https://travis-ci.org/sindresorhus/is-redirect)
2 +
3 +> Check if a number is a [redirect HTTP status code](http://en.wikipedia.org/wiki/List_of_HTTP_status_codes#3xx_Redirection)
4 +
5 +
6 +## Install
7 +
8 +```
9 +$ npm install --save is-redirect
10 +```
11 +
12 +
13 +## Usage
14 +
15 +```js
16 +var isRedirect = require('is-redirect');
17 +
18 +isRedirect(302);
19 +//=> true
20 +
21 +isRedirect(200);
22 +//=> false
23 +```
24 +
25 +
26 +## License
27 +
28 +MIT © [Sindre Sorhus](http://sindresorhus.com)
1 +'use strict';
2 +
3 +var WHITELIST = [
4 + 'ETIMEDOUT',
5 + 'ECONNRESET',
6 + 'EADDRINUSE',
7 + 'ESOCKETTIMEDOUT',
8 + 'ECONNREFUSED',
9 + 'EPIPE',
10 + 'EHOSTUNREACH',
11 + 'EAI_AGAIN'
12 +];
13 +
14 +var BLACKLIST = [
15 + 'ENOTFOUND',
16 + 'ENETUNREACH',
17 +
18 + // SSL errors from https://github.com/nodejs/node/blob/ed3d8b13ee9a705d89f9e0397d9e96519e7e47ac/src/node_crypto.cc#L1950
19 + 'UNABLE_TO_GET_ISSUER_CERT',
20 + 'UNABLE_TO_GET_CRL',
21 + 'UNABLE_TO_DECRYPT_CERT_SIGNATURE',
22 + 'UNABLE_TO_DECRYPT_CRL_SIGNATURE',
23 + 'UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY',
24 + 'CERT_SIGNATURE_FAILURE',
25 + 'CRL_SIGNATURE_FAILURE',
26 + 'CERT_NOT_YET_VALID',
27 + 'CERT_HAS_EXPIRED',
28 + 'CRL_NOT_YET_VALID',
29 + 'CRL_HAS_EXPIRED',
30 + 'ERROR_IN_CERT_NOT_BEFORE_FIELD',
31 + 'ERROR_IN_CERT_NOT_AFTER_FIELD',
32 + 'ERROR_IN_CRL_LAST_UPDATE_FIELD',
33 + 'ERROR_IN_CRL_NEXT_UPDATE_FIELD',
34 + 'OUT_OF_MEM',
35 + 'DEPTH_ZERO_SELF_SIGNED_CERT',
36 + 'SELF_SIGNED_CERT_IN_CHAIN',
37 + 'UNABLE_TO_GET_ISSUER_CERT_LOCALLY',
38 + 'UNABLE_TO_VERIFY_LEAF_SIGNATURE',
39 + 'CERT_CHAIN_TOO_LONG',
40 + 'CERT_REVOKED',
41 + 'INVALID_CA',
42 + 'PATH_LENGTH_EXCEEDED',
43 + 'INVALID_PURPOSE',
44 + 'CERT_UNTRUSTED',
45 + 'CERT_REJECTED'
46 +];
47 +
48 +module.exports = function (err) {
49 + if (!err || !err.code) {
50 + return true;
51 + }
52 +
53 + if (WHITELIST.indexOf(err.code) !== -1) {
54 + return true;
55 + }
56 +
57 + if (BLACKLIST.indexOf(err.code) !== -1) {
58 + return false;
59 + }
60 +
61 + return true;
62 +};
1 +The MIT License (MIT)
2 +
3 +Copyright (c) Vsevolod Strukchinsky <floatdrop@gmail.com> (github.com/floatdrop)
4 +
5 +Permission is hereby granted, free of charge, to any person obtaining a copy
6 +of this software and associated documentation files (the "Software"), to deal
7 +in the Software without restriction, including without limitation the rights
8 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 +copies of the Software, and to permit persons to whom the Software is
10 +furnished to do so, subject to the following conditions:
11 +
12 +The above copyright notice and this permission notice shall be included in
13 +all copies or substantial portions of the Software.
14 +
15 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 +THE SOFTWARE.
1 +{
2 + "name": "is-retry-allowed",
3 + "version": "1.2.0",
4 + "description": "Is retry allowed for Error?",
5 + "license": "MIT",
6 + "repository": "floatdrop/is-retry-allowed",
7 + "author": {
8 + "name": "Vsevolod Strukchinsky",
9 + "email": "floatdrop@gmail.com",
10 + "url": "github.com/floatdrop"
11 + },
12 + "engines": {
13 + "node": ">=0.10.0"
14 + },
15 + "scripts": {
16 + "test": "xo && ava"
17 + },
18 + "files": [
19 + "index.js"
20 + ],
21 + "keywords": [
22 + ""
23 + ],
24 + "dependencies": {},
25 + "devDependencies": {
26 + "ava": "^0.8.0",
27 + "xo": "^0.12.1"
28 + }
29 +}
1 +# is-retry-allowed [![Build Status](https://travis-ci.org/floatdrop/is-retry-allowed.svg?branch=master)](https://travis-ci.org/floatdrop/is-retry-allowed)
2 +
3 +Is retry allowed for Error?
4 +
5 +
6 +## Install
7 +
8 +```
9 +$ npm install --save is-retry-allowed
10 +```
11 +
12 +
13 +## Usage
14 +
15 +```js
16 +const isRetryAllowed = require('is-retry-allowed');
17 +
18 +isRetryAllowed({code: 'ETIMEDOUT'});
19 +//=> true
20 +
21 +isRetryAllowed({code: 'ENOTFOUND'});
22 +//=> false
23 +
24 +isRetryAllowed({});
25 +//=> true
26 +```
27 +
28 +
29 +## API
30 +
31 +### isRetryAllowed(error)
32 +
33 +#### error
34 +
35 +Type: `object`
36 +
37 +Object with `code` property, which will be used to determine retry.
38 +
39 +
40 +## License
41 +
42 +MIT © [Vsevolod Strukchinsky](http://github.com/floatdrop)
1 +'use strict';
2 +
3 +var isStream = module.exports = function (stream) {
4 + return stream !== null && typeof stream === 'object' && typeof stream.pipe === 'function';
5 +};
6 +
7 +isStream.writable = function (stream) {
8 + return isStream(stream) && stream.writable !== false && typeof stream._write === 'function' && typeof stream._writableState === 'object';
9 +};
10 +
11 +isStream.readable = function (stream) {
12 + return isStream(stream) && stream.readable !== false && typeof stream._read === 'function' && typeof stream._readableState === 'object';
13 +};
14 +
15 +isStream.duplex = function (stream) {
16 + return isStream.writable(stream) && isStream.readable(stream);
17 +};
18 +
19 +isStream.transform = function (stream) {
20 + return isStream.duplex(stream) && typeof stream._transform === 'function' && typeof stream._transformState === 'object';
21 +};
1 +The MIT License (MIT)
2 +
3 +Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
4 +
5 +Permission is hereby granted, free of charge, to any person obtaining a copy
6 +of this software and associated documentation files (the "Software"), to deal
7 +in the Software without restriction, including without limitation the rights
8 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 +copies of the Software, and to permit persons to whom the Software is
10 +furnished to do so, subject to the following conditions:
11 +
12 +The above copyright notice and this permission notice shall be included in
13 +all copies or substantial portions of the Software.
14 +
15 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 +THE SOFTWARE.
1 +{
2 + "name": "is-stream",
3 + "version": "1.1.0",
4 + "description": "Check if something is a Node.js stream",
5 + "license": "MIT",
6 + "repository": "sindresorhus/is-stream",
7 + "author": {
8 + "name": "Sindre Sorhus",
9 + "email": "sindresorhus@gmail.com",
10 + "url": "sindresorhus.com"
11 + },
12 + "engines": {
13 + "node": ">=0.10.0"
14 + },
15 + "scripts": {
16 + "test": "xo && ava"
17 + },
18 + "files": [
19 + "index.js"
20 + ],
21 + "keywords": [
22 + "stream",
23 + "type",
24 + "streams",
25 + "writable",
26 + "readable",
27 + "duplex",
28 + "transform",
29 + "check",
30 + "detect",
31 + "is"
32 + ],
33 + "devDependencies": {
34 + "ava": "*",
35 + "tempfile": "^1.1.0",
36 + "xo": "*"
37 + }
38 +}
1 +# is-stream [![Build Status](https://travis-ci.org/sindresorhus/is-stream.svg?branch=master)](https://travis-ci.org/sindresorhus/is-stream)
2 +
3 +> Check if something is a [Node.js stream](https://nodejs.org/api/stream.html)
4 +
5 +
6 +## Install
7 +
8 +```
9 +$ npm install --save is-stream
10 +```
11 +
12 +
13 +## Usage
14 +
15 +```js
16 +const fs = require('fs');
17 +const isStream = require('is-stream');
18 +
19 +isStream(fs.createReadStream('unicorn.png'));
20 +//=> true
21 +
22 +isStream({});
23 +//=> false
24 +```
25 +
26 +
27 +## API
28 +
29 +### isStream(stream)
30 +
31 +#### isStream.writable(stream)
32 +
33 +#### isStream.readable(stream)
34 +
35 +#### isStream.duplex(stream)
36 +
37 +#### isStream.transform(stream)
38 +
39 +
40 +## License
41 +
42 +MIT © [Sindre Sorhus](https://sindresorhus.com)
1 +'use strict';
2 +module.exports = function (obj) {
3 + var ret = {};
4 + var keys = Object.keys(Object(obj));
5 +
6 + for (var i = 0; i < keys.length; i++) {
7 + ret[keys[i].toLowerCase()] = obj[keys[i]];
8 + }
9 +
10 + return ret;
11 +};
1 +The MIT License (MIT)
2 +
3 +Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
4 +
5 +Permission is hereby granted, free of charge, to any person obtaining a copy
6 +of this software and associated documentation files (the "Software"), to deal
7 +in the Software without restriction, including without limitation the rights
8 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 +copies of the Software, and to permit persons to whom the Software is
10 +furnished to do so, subject to the following conditions:
11 +
12 +The above copyright notice and this permission notice shall be included in
13 +all copies or substantial portions of the Software.
14 +
15 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 +THE SOFTWARE.
1 +{
2 + "name": "lowercase-keys",
3 + "version": "1.0.1",
4 + "description": "Lowercase the keys of an object",
5 + "license": "MIT",
6 + "repository": "sindresorhus/lowercase-keys",
7 + "author": {
8 + "name": "Sindre Sorhus",
9 + "email": "sindresorhus@gmail.com",
10 + "url": "sindresorhus.com"
11 + },
12 + "engines": {
13 + "node": ">=0.10.0"
14 + },
15 + "scripts": {
16 + "test": "ava"
17 + },
18 + "files": [
19 + "index.js"
20 + ],
21 + "keywords": [
22 + "object",
23 + "assign",
24 + "extend",
25 + "properties",
26 + "lowercase",
27 + "lower-case",
28 + "case",
29 + "keys",
30 + "key"
31 + ],
32 + "devDependencies": {
33 + "ava": "*"
34 + }
35 +}
1 +# lowercase-keys [![Build Status](https://travis-ci.org/sindresorhus/lowercase-keys.svg?branch=master)](https://travis-ci.org/sindresorhus/lowercase-keys)
2 +
3 +> Lowercase the keys of an object
4 +
5 +
6 +## Install
7 +
8 +```
9 +$ npm install --save lowercase-keys
10 +```
11 +
12 +
13 +## Usage
14 +
15 +```js
16 +var lowercaseKeys = require('lowercase-keys');
17 +
18 +lowercaseKeys({FOO: true, bAr: false});
19 +//=> {foo: true, bar: false}
20 +```
21 +
22 +
23 +## API
24 +
25 +### lowercaseKeys(object)
26 +
27 +Lowercases the keys and returns a new object.
28 +
29 +
30 +
31 +## License
32 +
33 +MIT © [Sindre Sorhus](http://sindresorhus.com)
1 +'use strict';
2 +module.exports = function (url) {
3 + if (typeof url !== 'string') {
4 + throw new TypeError('Expected a string, got ' + typeof url);
5 + }
6 +
7 + url = url.trim();
8 +
9 + if (/^\.*\/|^(?!localhost)\w+:/.test(url)) {
10 + return url;
11 + }
12 +
13 + return url.replace(/^(?!(?:\w+:)?\/\/)/, 'http://');
14 +};
1 +The MIT License (MIT)
2 +
3 +Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
4 +
5 +Permission is hereby granted, free of charge, to any person obtaining a copy
6 +of this software and associated documentation files (the "Software"), to deal
7 +in the Software without restriction, including without limitation the rights
8 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 +copies of the Software, and to permit persons to whom the Software is
10 +furnished to do so, subject to the following conditions:
11 +
12 +The above copyright notice and this permission notice shall be included in
13 +all copies or substantial portions of the Software.
14 +
15 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 +THE SOFTWARE.
1 +{
2 + "name": "prepend-http",
3 + "version": "1.0.4",
4 + "description": "Prepend `http://` to humanized URLs like todomvc.com and localhost",
5 + "license": "MIT",
6 + "repository": "sindresorhus/prepend-http",
7 + "author": {
8 + "name": "Sindre Sorhus",
9 + "email": "sindresorhus@gmail.com",
10 + "url": "sindresorhus.com"
11 + },
12 + "engines": {
13 + "node": ">=0.10.0"
14 + },
15 + "scripts": {
16 + "test": "xo && ava"
17 + },
18 + "files": [
19 + "index.js"
20 + ],
21 + "keywords": [
22 + "prepend",
23 + "protocol",
24 + "scheme",
25 + "url",
26 + "uri",
27 + "http",
28 + "https",
29 + "humanized"
30 + ],
31 + "devDependencies": {
32 + "ava": "*",
33 + "xo": "*"
34 + }
35 +}
1 +# prepend-http [![Build Status](https://travis-ci.org/sindresorhus/prepend-http.svg?branch=master)](https://travis-ci.org/sindresorhus/prepend-http)
2 +
3 +> Prepend `http://` to humanized URLs like `todomvc.com` and `localhost`
4 +
5 +
6 +## Install
7 +
8 +```
9 +$ npm install --save prepend-http
10 +```
11 +
12 +
13 +## Usage
14 +
15 +```js
16 +const prependHttp = require('prepend-http');
17 +
18 +prependHttp('todomvc.com');
19 +//=> 'http://todomvc.com'
20 +
21 +prependHttp('localhost');
22 +//=> 'http://localhost'
23 +
24 +prependHttp('http://todomvc.com');
25 +//=> 'http://todomvc.com'
26 +```
27 +
28 +
29 +## License
30 +
31 +MIT © [Sindre Sorhus](https://sindresorhus.com)
1 +'use strict';
2 +
3 +const got = require('got');
4 +const uniqueRandomArray = require('unique-random-array');
5 +const EventEmitter = require('eventemitter3');
6 +
7 +const randomCache = {};
8 +
9 +function formatResult(getRandomImage) {
10 + const imageData = getRandomImage();
11 + if (!imageData) {
12 + return;
13 + }
14 + return `http://imgur.com/${imageData.hash}${imageData.ext.replace(/\?.*/, '')}`;
15 +}
16 +
17 +function storeResults(images, subreddit) {
18 + const getRandomImage = uniqueRandomArray(images);
19 +
20 + randomCache[subreddit] = getRandomImage;
21 + return getRandomImage;
22 +}
23 +
24 +function randomPuppy(subreddit) {
25 + subreddit = (typeof subreddit === 'string' && subreddit.length !== 0) ? subreddit : 'puppies';
26 +
27 + if (randomCache[subreddit]) {
28 + return Promise.resolve(formatResult(randomCache[subreddit]));
29 + }
30 +
31 + return got(`https://imgur.com/r/${subreddit}/hot.json`, {json: true})
32 + .then(response => storeResults(response.body.data, subreddit))
33 + .then(getRandomImage => formatResult(getRandomImage));
34 +}
35 +
36 +// silly feature to play with observables
37 +function all(subreddit) {
38 + const eventEmitter = new EventEmitter();
39 +
40 + function emitRandomImage(subreddit) {
41 + randomPuppy(subreddit).then(imageUrl => {
42 + eventEmitter.emit('data', imageUrl + '#' + subreddit);
43 + if (eventEmitter.listeners('data').length) {
44 + setTimeout(() => emitRandomImage(subreddit), 200);
45 + }
46 + });
47 + }
48 +
49 + emitRandomImage(subreddit);
50 + return eventEmitter;
51 +}
52 +
53 +function callback(subreddit, cb) {
54 + randomPuppy(subreddit)
55 + .then(url => cb(null, url))
56 + .catch(err => cb(err));
57 +}
58 +
59 +// subreddit is optional
60 +// callback support is provided for a training exercise
61 +module.exports = (subreddit, cb) => {
62 + if (typeof cb === 'function') {
63 + callback(subreddit, cb);
64 + } else if (typeof subreddit === 'function') {
65 + callback(null, subreddit);
66 + } else {
67 + return randomPuppy(subreddit);
68 + }
69 +};
70 +
71 +module.exports.all = all;
1 +The MIT License (MIT)
2 +
3 +Copyright (c) Dylan Greene <dylang@gmail.com> (github.com/dylang)
4 +
5 +Permission is hereby granted, free of charge, to any person obtaining a copy
6 +of this software and associated documentation files (the "Software"), to deal
7 +in the Software without restriction, including without limitation the rights
8 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 +copies of the Software, and to permit persons to whom the Software is
10 +furnished to do so, subject to the following conditions:
11 +
12 +The above copyright notice and this permission notice shall be included in
13 +all copies or substantial portions of the Software.
14 +
15 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 +THE SOFTWARE.
1 +{
2 + "name": "random-puppy",
3 + "version": "1.1.0",
4 + "description": "Get a random imgur image url, by default a puppy.",
5 + "license": "MIT",
6 + "repository": "dylang/random-puppy",
7 + "author": {
8 + "name": "Dylan Greene",
9 + "email": "dylang@gmail.com",
10 + "url": "github.com/dylang"
11 + },
12 + "engines": {
13 + "node": ">=4.0.0"
14 + },
15 + "scripts": {
16 + "test": "xo && ava",
17 + "watch": "ava --watch"
18 + },
19 + "files": [
20 + "index.js"
21 + ],
22 + "keywords": [
23 + "puppy",
24 + "doggie",
25 + "dog",
26 + "imgur",
27 + "random",
28 + "placeholder"
29 + ],
30 + "dependencies": {
31 + "eventemitter3": "^1.2.0",
32 + "got": "^6.3.0",
33 + "unique-random-array": "^1.0.0"
34 + },
35 + "devDependencies": {
36 + "ava": "^0.14.0",
37 + "rx-lite": "^4.0.8",
38 + "xo": "^0.14.0"
39 + },
40 + "xo": {
41 + "space": 4
42 + }
43 +}
1 +# random-puppy [![Build Status](https://travis-ci.org/dylang/random-puppy.svg?branch=master)](https://travis-ci.org/dylang/random-puppy)
2 +
3 +> Get a random puppy image url.
4 +
5 +<img src="http://i.imgur.com/0zZ8m6B.jpg" width="300px">
6 +
7 +## Install
8 +
9 +```
10 +$ npm install --save random-puppy
11 +```
12 +
13 +
14 +## Usage
15 +
16 +```js
17 +const randomPuppy = require('random-puppy');
18 +
19 +randomPuppy()
20 + .then(url => {
21 + console.log(url);
22 + })
23 +
24 +//=> 'http://imgur.com/IoI8uS5'
25 +```
26 +
27 +
28 +## API
29 +
30 +### `randomPuppy()`
31 +
32 +Returns a `promise` for a random puppy image url from http://imgur.com/ from https://www.reddit.com/r/puppy
33 +
34 +### `randomPuppy(subreddit)`
35 +
36 +Returns a `promise` for a random image url from the selected subreddit. *Warning: We cannot promise it will be a image of a puppy!*
37 +
38 +### `randomPuppy.all(subreddit)`
39 +
40 +Returns an `eventemitter` for getting all random images for a subreddit.
41 +
42 +```js
43 +const event = randomPuppy.all(subreddit);
44 +event.on('data', url => console.log(url));
45 +```
46 +
47 +Or:
48 +```js
49 +const event = randomPuppy.all('puppies');
50 +
51 +Observable.fromEvent(event, 'data')
52 + .subscribe(data => {
53 + console.log(data);
54 + });
55 +```
56 +
57 +## Notes
58 +
59 +* Node 4 or newer.
60 +* Caches results from imgur in memory.
61 +* Created for the purpose of using in a training exercise on different ways to do async in JavaScript at [Opower](https://opower.com/).
62 +
63 +## License
64 +
65 +MIT © [Dylan Greene](https://github.com/dylang)
1 +The MIT License (MIT)
2 +
3 +Copyright (c) Feross Aboukhadijeh
4 +
5 +Permission is hereby granted, free of charge, to any person obtaining a copy
6 +of this software and associated documentation files (the "Software"), to deal
7 +in the Software without restriction, including without limitation the rights
8 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 +copies of the Software, and to permit persons to whom the Software is
10 +furnished to do so, subject to the following conditions:
11 +
12 +The above copyright notice and this permission notice shall be included in
13 +all copies or substantial portions of the Software.
14 +
15 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 +THE SOFTWARE.
1 +# safe-buffer [![travis][travis-image]][travis-url] [![npm][npm-image]][npm-url] [![downloads][downloads-image]][downloads-url] [![javascript style guide][standard-image]][standard-url]
2 +
3 +[travis-image]: https://img.shields.io/travis/feross/safe-buffer/master.svg
4 +[travis-url]: https://travis-ci.org/feross/safe-buffer
5 +[npm-image]: https://img.shields.io/npm/v/safe-buffer.svg
6 +[npm-url]: https://npmjs.org/package/safe-buffer
7 +[downloads-image]: https://img.shields.io/npm/dm/safe-buffer.svg
8 +[downloads-url]: https://npmjs.org/package/safe-buffer
9 +[standard-image]: https://img.shields.io/badge/code_style-standard-brightgreen.svg
10 +[standard-url]: https://standardjs.com
11 +
12 +#### Safer Node.js Buffer API
13 +
14 +**Use the new Node.js Buffer APIs (`Buffer.from`, `Buffer.alloc`,
15 +`Buffer.allocUnsafe`, `Buffer.allocUnsafeSlow`) in all versions of Node.js.**
16 +
17 +**Uses the built-in implementation when available.**
18 +
19 +## install
20 +
21 +```
22 +npm install safe-buffer
23 +```
24 +
25 +## usage
26 +
27 +The goal of this package is to provide a safe replacement for the node.js `Buffer`.
28 +
29 +It's a drop-in replacement for `Buffer`. You can use it by adding one `require` line to
30 +the top of your node.js modules:
31 +
32 +```js
33 +var Buffer = require('safe-buffer').Buffer
34 +
35 +// Existing buffer code will continue to work without issues:
36 +
37 +new Buffer('hey', 'utf8')
38 +new Buffer([1, 2, 3], 'utf8')
39 +new Buffer(obj)
40 +new Buffer(16) // create an uninitialized buffer (potentially unsafe)
41 +
42 +// But you can use these new explicit APIs to make clear what you want:
43 +
44 +Buffer.from('hey', 'utf8') // convert from many types to a Buffer
45 +Buffer.alloc(16) // create a zero-filled buffer (safe)
46 +Buffer.allocUnsafe(16) // create an uninitialized buffer (potentially unsafe)
47 +```
48 +
49 +## api
50 +
51 +### Class Method: Buffer.from(array)
52 +<!-- YAML
53 +added: v3.0.0
54 +-->
55 +
56 +* `array` {Array}
57 +
58 +Allocates a new `Buffer` using an `array` of octets.
59 +
60 +```js
61 +const buf = Buffer.from([0x62,0x75,0x66,0x66,0x65,0x72]);
62 + // creates a new Buffer containing ASCII bytes
63 + // ['b','u','f','f','e','r']
64 +```
65 +
66 +A `TypeError` will be thrown if `array` is not an `Array`.
67 +
68 +### Class Method: Buffer.from(arrayBuffer[, byteOffset[, length]])
69 +<!-- YAML
70 +added: v5.10.0
71 +-->
72 +
73 +* `arrayBuffer` {ArrayBuffer} The `.buffer` property of a `TypedArray` or
74 + a `new ArrayBuffer()`
75 +* `byteOffset` {Number} Default: `0`
76 +* `length` {Number} Default: `arrayBuffer.length - byteOffset`
77 +
78 +When passed a reference to the `.buffer` property of a `TypedArray` instance,
79 +the newly created `Buffer` will share the same allocated memory as the
80 +TypedArray.
81 +
82 +```js
83 +const arr = new Uint16Array(2);
84 +arr[0] = 5000;
85 +arr[1] = 4000;
86 +
87 +const buf = Buffer.from(arr.buffer); // shares the memory with arr;
88 +
89 +console.log(buf);
90 + // Prints: <Buffer 88 13 a0 0f>
91 +
92 +// changing the TypedArray changes the Buffer also
93 +arr[1] = 6000;
94 +
95 +console.log(buf);
96 + // Prints: <Buffer 88 13 70 17>
97 +```
98 +
99 +The optional `byteOffset` and `length` arguments specify a memory range within
100 +the `arrayBuffer` that will be shared by the `Buffer`.
101 +
102 +```js
103 +const ab = new ArrayBuffer(10);
104 +const buf = Buffer.from(ab, 0, 2);
105 +console.log(buf.length);
106 + // Prints: 2
107 +```
108 +
109 +A `TypeError` will be thrown if `arrayBuffer` is not an `ArrayBuffer`.
110 +
111 +### Class Method: Buffer.from(buffer)
112 +<!-- YAML
113 +added: v3.0.0
114 +-->
115 +
116 +* `buffer` {Buffer}
117 +
118 +Copies the passed `buffer` data onto a new `Buffer` instance.
119 +
120 +```js
121 +const buf1 = Buffer.from('buffer');
122 +const buf2 = Buffer.from(buf1);
123 +
124 +buf1[0] = 0x61;
125 +console.log(buf1.toString());
126 + // 'auffer'
127 +console.log(buf2.toString());
128 + // 'buffer' (copy is not changed)
129 +```
130 +
131 +A `TypeError` will be thrown if `buffer` is not a `Buffer`.
132 +
133 +### Class Method: Buffer.from(str[, encoding])
134 +<!-- YAML
135 +added: v5.10.0
136 +-->
137 +
138 +* `str` {String} String to encode.
139 +* `encoding` {String} Encoding to use, Default: `'utf8'`
140 +
141 +Creates a new `Buffer` containing the given JavaScript string `str`. If
142 +provided, the `encoding` parameter identifies the character encoding.
143 +If not provided, `encoding` defaults to `'utf8'`.
144 +
145 +```js
146 +const buf1 = Buffer.from('this is a tést');
147 +console.log(buf1.toString());
148 + // prints: this is a tést
149 +console.log(buf1.toString('ascii'));
150 + // prints: this is a tC)st
151 +
152 +const buf2 = Buffer.from('7468697320697320612074c3a97374', 'hex');
153 +console.log(buf2.toString());
154 + // prints: this is a tést
155 +```
156 +
157 +A `TypeError` will be thrown if `str` is not a string.
158 +
159 +### Class Method: Buffer.alloc(size[, fill[, encoding]])
160 +<!-- YAML
161 +added: v5.10.0
162 +-->
163 +
164 +* `size` {Number}
165 +* `fill` {Value} Default: `undefined`
166 +* `encoding` {String} Default: `utf8`
167 +
168 +Allocates a new `Buffer` of `size` bytes. If `fill` is `undefined`, the
169 +`Buffer` will be *zero-filled*.
170 +
171 +```js
172 +const buf = Buffer.alloc(5);
173 +console.log(buf);
174 + // <Buffer 00 00 00 00 00>
175 +```
176 +
177 +The `size` must be less than or equal to the value of
178 +`require('buffer').kMaxLength` (on 64-bit architectures, `kMaxLength` is
179 +`(2^31)-1`). Otherwise, a [`RangeError`][] is thrown. A zero-length Buffer will
180 +be created if a `size` less than or equal to 0 is specified.
181 +
182 +If `fill` is specified, the allocated `Buffer` will be initialized by calling
183 +`buf.fill(fill)`. See [`buf.fill()`][] for more information.
184 +
185 +```js
186 +const buf = Buffer.alloc(5, 'a');
187 +console.log(buf);
188 + // <Buffer 61 61 61 61 61>
189 +```
190 +
191 +If both `fill` and `encoding` are specified, the allocated `Buffer` will be
192 +initialized by calling `buf.fill(fill, encoding)`. For example:
193 +
194 +```js
195 +const buf = Buffer.alloc(11, 'aGVsbG8gd29ybGQ=', 'base64');
196 +console.log(buf);
197 + // <Buffer 68 65 6c 6c 6f 20 77 6f 72 6c 64>
198 +```
199 +
200 +Calling `Buffer.alloc(size)` can be significantly slower than the alternative
201 +`Buffer.allocUnsafe(size)` but ensures that the newly created `Buffer` instance
202 +contents will *never contain sensitive data*.
203 +
204 +A `TypeError` will be thrown if `size` is not a number.
205 +
206 +### Class Method: Buffer.allocUnsafe(size)
207 +<!-- YAML
208 +added: v5.10.0
209 +-->
210 +
211 +* `size` {Number}
212 +
213 +Allocates a new *non-zero-filled* `Buffer` of `size` bytes. The `size` must
214 +be less than or equal to the value of `require('buffer').kMaxLength` (on 64-bit
215 +architectures, `kMaxLength` is `(2^31)-1`). Otherwise, a [`RangeError`][] is
216 +thrown. A zero-length Buffer will be created if a `size` less than or equal to
217 +0 is specified.
218 +
219 +The underlying memory for `Buffer` instances created in this way is *not
220 +initialized*. The contents of the newly created `Buffer` are unknown and
221 +*may contain sensitive data*. Use [`buf.fill(0)`][] to initialize such
222 +`Buffer` instances to zeroes.
223 +
224 +```js
225 +const buf = Buffer.allocUnsafe(5);
226 +console.log(buf);
227 + // <Buffer 78 e0 82 02 01>
228 + // (octets will be different, every time)
229 +buf.fill(0);
230 +console.log(buf);
231 + // <Buffer 00 00 00 00 00>
232 +```
233 +
234 +A `TypeError` will be thrown if `size` is not a number.
235 +
236 +Note that the `Buffer` module pre-allocates an internal `Buffer` instance of
237 +size `Buffer.poolSize` that is used as a pool for the fast allocation of new
238 +`Buffer` instances created using `Buffer.allocUnsafe(size)` (and the deprecated
239 +`new Buffer(size)` constructor) only when `size` is less than or equal to
240 +`Buffer.poolSize >> 1` (floor of `Buffer.poolSize` divided by two). The default
241 +value of `Buffer.poolSize` is `8192` but can be modified.
242 +
243 +Use of this pre-allocated internal memory pool is a key difference between
244 +calling `Buffer.alloc(size, fill)` vs. `Buffer.allocUnsafe(size).fill(fill)`.
245 +Specifically, `Buffer.alloc(size, fill)` will *never* use the internal Buffer
246 +pool, while `Buffer.allocUnsafe(size).fill(fill)` *will* use the internal
247 +Buffer pool if `size` is less than or equal to half `Buffer.poolSize`. The
248 +difference is subtle but can be important when an application requires the
249 +additional performance that `Buffer.allocUnsafe(size)` provides.
250 +
251 +### Class Method: Buffer.allocUnsafeSlow(size)
252 +<!-- YAML
253 +added: v5.10.0
254 +-->
255 +
256 +* `size` {Number}
257 +
258 +Allocates a new *non-zero-filled* and non-pooled `Buffer` of `size` bytes. The
259 +`size` must be less than or equal to the value of
260 +`require('buffer').kMaxLength` (on 64-bit architectures, `kMaxLength` is
261 +`(2^31)-1`). Otherwise, a [`RangeError`][] is thrown. A zero-length Buffer will
262 +be created if a `size` less than or equal to 0 is specified.
263 +
264 +The underlying memory for `Buffer` instances created in this way is *not
265 +initialized*. The contents of the newly created `Buffer` are unknown and
266 +*may contain sensitive data*. Use [`buf.fill(0)`][] to initialize such
267 +`Buffer` instances to zeroes.
268 +
269 +When using `Buffer.allocUnsafe()` to allocate new `Buffer` instances,
270 +allocations under 4KB are, by default, sliced from a single pre-allocated
271 +`Buffer`. This allows applications to avoid the garbage collection overhead of
272 +creating many individually allocated Buffers. This approach improves both
273 +performance and memory usage by eliminating the need to track and cleanup as
274 +many `Persistent` objects.
275 +
276 +However, in the case where a developer may need to retain a small chunk of
277 +memory from a pool for an indeterminate amount of time, it may be appropriate
278 +to create an un-pooled Buffer instance using `Buffer.allocUnsafeSlow()` then
279 +copy out the relevant bits.
280 +
281 +```js
282 +// need to keep around a few small chunks of memory
283 +const store = [];
284 +
285 +socket.on('readable', () => {
286 + const data = socket.read();
287 + // allocate for retained data
288 + const sb = Buffer.allocUnsafeSlow(10);
289 + // copy the data into the new allocation
290 + data.copy(sb, 0, 0, 10);
291 + store.push(sb);
292 +});
293 +```
294 +
295 +Use of `Buffer.allocUnsafeSlow()` should be used only as a last resort *after*
296 +a developer has observed undue memory retention in their applications.
297 +
298 +A `TypeError` will be thrown if `size` is not a number.
299 +
300 +### All the Rest
301 +
302 +The rest of the `Buffer` API is exactly the same as in node.js.
303 +[See the docs](https://nodejs.org/api/buffer.html).
304 +
305 +
306 +## Related links
307 +
308 +- [Node.js issue: Buffer(number) is unsafe](https://github.com/nodejs/node/issues/4660)
309 +- [Node.js Enhancement Proposal: Buffer.from/Buffer.alloc/Buffer.zalloc/Buffer() soft-deprecate](https://github.com/nodejs/node-eps/pull/4)
310 +
311 +## Why is `Buffer` unsafe?
312 +
313 +Today, the node.js `Buffer` constructor is overloaded to handle many different argument
314 +types like `String`, `Array`, `Object`, `TypedArrayView` (`Uint8Array`, etc.),
315 +`ArrayBuffer`, and also `Number`.
316 +
317 +The API is optimized for convenience: you can throw any type at it, and it will try to do
318 +what you want.
319 +
320 +Because the Buffer constructor is so powerful, you often see code like this:
321 +
322 +```js
323 +// Convert UTF-8 strings to hex
324 +function toHex (str) {
325 + return new Buffer(str).toString('hex')
326 +}
327 +```
328 +
329 +***But what happens if `toHex` is called with a `Number` argument?***
330 +
331 +### Remote Memory Disclosure
332 +
333 +If an attacker can make your program call the `Buffer` constructor with a `Number`
334 +argument, then they can make it allocate uninitialized memory from the node.js process.
335 +This could potentially disclose TLS private keys, user data, or database passwords.
336 +
337 +When the `Buffer` constructor is passed a `Number` argument, it returns an
338 +**UNINITIALIZED** block of memory of the specified `size`. When you create a `Buffer` like
339 +this, you **MUST** overwrite the contents before returning it to the user.
340 +
341 +From the [node.js docs](https://nodejs.org/api/buffer.html#buffer_new_buffer_size):
342 +
343 +> `new Buffer(size)`
344 +>
345 +> - `size` Number
346 +>
347 +> The underlying memory for `Buffer` instances created in this way is not initialized.
348 +> **The contents of a newly created `Buffer` are unknown and could contain sensitive
349 +> data.** Use `buf.fill(0)` to initialize a Buffer to zeroes.
350 +
351 +(Emphasis our own.)
352 +
353 +Whenever the programmer intended to create an uninitialized `Buffer` you often see code
354 +like this:
355 +
356 +```js
357 +var buf = new Buffer(16)
358 +
359 +// Immediately overwrite the uninitialized buffer with data from another buffer
360 +for (var i = 0; i < buf.length; i++) {
361 + buf[i] = otherBuf[i]
362 +}
363 +```
364 +
365 +
366 +### Would this ever be a problem in real code?
367 +
368 +Yes. It's surprisingly common to forget to check the type of your variables in a
369 +dynamically-typed language like JavaScript.
370 +
371 +Usually the consequences of assuming the wrong type is that your program crashes with an
372 +uncaught exception. But the failure mode for forgetting to check the type of arguments to
373 +the `Buffer` constructor is more catastrophic.
374 +
375 +Here's an example of a vulnerable service that takes a JSON payload and converts it to
376 +hex:
377 +
378 +```js
379 +// Take a JSON payload {str: "some string"} and convert it to hex
380 +var server = http.createServer(function (req, res) {
381 + var data = ''
382 + req.setEncoding('utf8')
383 + req.on('data', function (chunk) {
384 + data += chunk
385 + })
386 + req.on('end', function () {
387 + var body = JSON.parse(data)
388 + res.end(new Buffer(body.str).toString('hex'))
389 + })
390 +})
391 +
392 +server.listen(8080)
393 +```
394 +
395 +In this example, an http client just has to send:
396 +
397 +```json
398 +{
399 + "str": 1000
400 +}
401 +```
402 +
403 +and it will get back 1,000 bytes of uninitialized memory from the server.
404 +
405 +This is a very serious bug. It's similar in severity to the
406 +[the Heartbleed bug](http://heartbleed.com/) that allowed disclosure of OpenSSL process
407 +memory by remote attackers.
408 +
409 +
410 +### Which real-world packages were vulnerable?
411 +
412 +#### [`bittorrent-dht`](https://www.npmjs.com/package/bittorrent-dht)
413 +
414 +[Mathias Buus](https://github.com/mafintosh) and I
415 +([Feross Aboukhadijeh](http://feross.org/)) found this issue in one of our own packages,
416 +[`bittorrent-dht`](https://www.npmjs.com/package/bittorrent-dht). The bug would allow
417 +anyone on the internet to send a series of messages to a user of `bittorrent-dht` and get
418 +them to reveal 20 bytes at a time of uninitialized memory from the node.js process.
419 +
420 +Here's
421 +[the commit](https://github.com/feross/bittorrent-dht/commit/6c7da04025d5633699800a99ec3fbadf70ad35b8)
422 +that fixed it. We released a new fixed version, created a
423 +[Node Security Project disclosure](https://nodesecurity.io/advisories/68), and deprecated all
424 +vulnerable versions on npm so users will get a warning to upgrade to a newer version.
425 +
426 +#### [`ws`](https://www.npmjs.com/package/ws)
427 +
428 +That got us wondering if there were other vulnerable packages. Sure enough, within a short
429 +period of time, we found the same issue in [`ws`](https://www.npmjs.com/package/ws), the
430 +most popular WebSocket implementation in node.js.
431 +
432 +If certain APIs were called with `Number` parameters instead of `String` or `Buffer` as
433 +expected, then uninitialized server memory would be disclosed to the remote peer.
434 +
435 +These were the vulnerable methods:
436 +
437 +```js
438 +socket.send(number)
439 +socket.ping(number)
440 +socket.pong(number)
441 +```
442 +
443 +Here's a vulnerable socket server with some echo functionality:
444 +
445 +```js
446 +server.on('connection', function (socket) {
447 + socket.on('message', function (message) {
448 + message = JSON.parse(message)
449 + if (message.type === 'echo') {
450 + socket.send(message.data) // send back the user's message
451 + }
452 + })
453 +})
454 +```
455 +
456 +`socket.send(number)` called on the server, will disclose server memory.
457 +
458 +Here's [the release](https://github.com/websockets/ws/releases/tag/1.0.1) where the issue
459 +was fixed, with a more detailed explanation. Props to
460 +[Arnout Kazemier](https://github.com/3rd-Eden) for the quick fix. Here's the
461 +[Node Security Project disclosure](https://nodesecurity.io/advisories/67).
462 +
463 +
464 +### What's the solution?
465 +
466 +It's important that node.js offers a fast way to get memory otherwise performance-critical
467 +applications would needlessly get a lot slower.
468 +
469 +But we need a better way to *signal our intent* as programmers. **When we want
470 +uninitialized memory, we should request it explicitly.**
471 +
472 +Sensitive functionality should not be packed into a developer-friendly API that loosely
473 +accepts many different types. This type of API encourages the lazy practice of passing
474 +variables in without checking the type very carefully.
475 +
476 +#### A new API: `Buffer.allocUnsafe(number)`
477 +
478 +The functionality of creating buffers with uninitialized memory should be part of another
479 +API. We propose `Buffer.allocUnsafe(number)`. This way, it's not part of an API that
480 +frequently gets user input of all sorts of different types passed into it.
481 +
482 +```js
483 +var buf = Buffer.allocUnsafe(16) // careful, uninitialized memory!
484 +
485 +// Immediately overwrite the uninitialized buffer with data from another buffer
486 +for (var i = 0; i < buf.length; i++) {
487 + buf[i] = otherBuf[i]
488 +}
489 +```
490 +
491 +
492 +### How do we fix node.js core?
493 +
494 +We sent [a PR to node.js core](https://github.com/nodejs/node/pull/4514) (merged as
495 +`semver-major`) which defends against one case:
496 +
497 +```js
498 +var str = 16
499 +new Buffer(str, 'utf8')
500 +```
501 +
502 +In this situation, it's implied that the programmer intended the first argument to be a
503 +string, since they passed an encoding as a second argument. Today, node.js will allocate
504 +uninitialized memory in the case of `new Buffer(number, encoding)`, which is probably not
505 +what the programmer intended.
506 +
507 +But this is only a partial solution, since if the programmer does `new Buffer(variable)`
508 +(without an `encoding` parameter) there's no way to know what they intended. If `variable`
509 +is sometimes a number, then uninitialized memory will sometimes be returned.
510 +
511 +### What's the real long-term fix?
512 +
513 +We could deprecate and remove `new Buffer(number)` and use `Buffer.allocUnsafe(number)` when
514 +we need uninitialized memory. But that would break 1000s of packages.
515 +
516 +~~We believe the best solution is to:~~
517 +
518 +~~1. Change `new Buffer(number)` to return safe, zeroed-out memory~~
519 +
520 +~~2. Create a new API for creating uninitialized Buffers. We propose: `Buffer.allocUnsafe(number)`~~
521 +
522 +#### Update
523 +
524 +We now support adding three new APIs:
525 +
526 +- `Buffer.from(value)` - convert from any type to a buffer
527 +- `Buffer.alloc(size)` - create a zero-filled buffer
528 +- `Buffer.allocUnsafe(size)` - create an uninitialized buffer with given size
529 +
530 +This solves the core problem that affected `ws` and `bittorrent-dht` which is
531 +`Buffer(variable)` getting tricked into taking a number argument.
532 +
533 +This way, existing code continues working and the impact on the npm ecosystem will be
534 +minimal. Over time, npm maintainers can migrate performance-critical code to use
535 +`Buffer.allocUnsafe(number)` instead of `new Buffer(number)`.
536 +
537 +
538 +### Conclusion
539 +
540 +We think there's a serious design issue with the `Buffer` API as it exists today. It
541 +promotes insecure software by putting high-risk functionality into a convenient API
542 +with friendly "developer ergonomics".
543 +
544 +This wasn't merely a theoretical exercise because we found the issue in some of the
545 +most popular npm packages.
546 +
547 +Fortunately, there's an easy fix that can be applied today. Use `safe-buffer` in place of
548 +`buffer`.
549 +
550 +```js
551 +var Buffer = require('safe-buffer').Buffer
552 +```
553 +
554 +Eventually, we hope that node.js core can switch to this new, safer behavior. We believe
555 +the impact on the ecosystem would be minimal since it's not a breaking change.
556 +Well-maintained, popular packages would be updated to use `Buffer.alloc` quickly, while
557 +older, insecure packages would magically become safe from this attack vector.
558 +
559 +
560 +## links
561 +
562 +- [Node.js PR: buffer: throw if both length and enc are passed](https://github.com/nodejs/node/pull/4514)
563 +- [Node Security Project disclosure for `ws`](https://nodesecurity.io/advisories/67)
564 +- [Node Security Project disclosure for`bittorrent-dht`](https://nodesecurity.io/advisories/68)
565 +
566 +
567 +## credit
568 +
569 +The original issues in `bittorrent-dht`
570 +([disclosure](https://nodesecurity.io/advisories/68)) and
571 +`ws` ([disclosure](https://nodesecurity.io/advisories/67)) were discovered by
572 +[Mathias Buus](https://github.com/mafintosh) and
573 +[Feross Aboukhadijeh](http://feross.org/).
574 +
575 +Thanks to [Adam Baldwin](https://github.com/evilpacket) for helping disclose these issues
576 +and for his work running the [Node Security Project](https://nodesecurity.io/).
577 +
578 +Thanks to [John Hiesey](https://github.com/jhiesey) for proofreading this README and
579 +auditing the code.
580 +
581 +
582 +## license
583 +
584 +MIT. Copyright (C) [Feross Aboukhadijeh](http://feross.org)
1 +declare module "safe-buffer" {
2 + export class Buffer {
3 + length: number
4 + write(string: string, offset?: number, length?: number, encoding?: string): number;
5 + toString(encoding?: string, start?: number, end?: number): string;
6 + toJSON(): { type: 'Buffer', data: any[] };
7 + equals(otherBuffer: Buffer): boolean;
8 + compare(otherBuffer: Buffer, targetStart?: number, targetEnd?: number, sourceStart?: number, sourceEnd?: number): number;
9 + copy(targetBuffer: Buffer, targetStart?: number, sourceStart?: number, sourceEnd?: number): number;
10 + slice(start?: number, end?: number): Buffer;
11 + writeUIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;
12 + writeUIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;
13 + writeIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;
14 + writeIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;
15 + readUIntLE(offset: number, byteLength: number, noAssert?: boolean): number;
16 + readUIntBE(offset: number, byteLength: number, noAssert?: boolean): number;
17 + readIntLE(offset: number, byteLength: number, noAssert?: boolean): number;
18 + readIntBE(offset: number, byteLength: number, noAssert?: boolean): number;
19 + readUInt8(offset: number, noAssert?: boolean): number;
20 + readUInt16LE(offset: number, noAssert?: boolean): number;
21 + readUInt16BE(offset: number, noAssert?: boolean): number;
22 + readUInt32LE(offset: number, noAssert?: boolean): number;
23 + readUInt32BE(offset: number, noAssert?: boolean): number;
24 + readInt8(offset: number, noAssert?: boolean): number;
25 + readInt16LE(offset: number, noAssert?: boolean): number;
26 + readInt16BE(offset: number, noAssert?: boolean): number;
27 + readInt32LE(offset: number, noAssert?: boolean): number;
28 + readInt32BE(offset: number, noAssert?: boolean): number;
29 + readFloatLE(offset: number, noAssert?: boolean): number;
30 + readFloatBE(offset: number, noAssert?: boolean): number;
31 + readDoubleLE(offset: number, noAssert?: boolean): number;
32 + readDoubleBE(offset: number, noAssert?: boolean): number;
33 + swap16(): Buffer;
34 + swap32(): Buffer;
35 + swap64(): Buffer;
36 + writeUInt8(value: number, offset: number, noAssert?: boolean): number;
37 + writeUInt16LE(value: number, offset: number, noAssert?: boolean): number;
38 + writeUInt16BE(value: number, offset: number, noAssert?: boolean): number;
39 + writeUInt32LE(value: number, offset: number, noAssert?: boolean): number;
40 + writeUInt32BE(value: number, offset: number, noAssert?: boolean): number;
41 + writeInt8(value: number, offset: number, noAssert?: boolean): number;
42 + writeInt16LE(value: number, offset: number, noAssert?: boolean): number;
43 + writeInt16BE(value: number, offset: number, noAssert?: boolean): number;
44 + writeInt32LE(value: number, offset: number, noAssert?: boolean): number;
45 + writeInt32BE(value: number, offset: number, noAssert?: boolean): number;
46 + writeFloatLE(value: number, offset: number, noAssert?: boolean): number;
47 + writeFloatBE(value: number, offset: number, noAssert?: boolean): number;
48 + writeDoubleLE(value: number, offset: number, noAssert?: boolean): number;
49 + writeDoubleBE(value: number, offset: number, noAssert?: boolean): number;
50 + fill(value: any, offset?: number, end?: number): this;
51 + indexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number;
52 + lastIndexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number;
53 + includes(value: string | number | Buffer, byteOffset?: number, encoding?: string): boolean;
54 +
55 + /**
56 + * Allocates a new buffer containing the given {str}.
57 + *
58 + * @param str String to store in buffer.
59 + * @param encoding encoding to use, optional. Default is 'utf8'
60 + */
61 + constructor (str: string, encoding?: string);
62 + /**
63 + * Allocates a new buffer of {size} octets.
64 + *
65 + * @param size count of octets to allocate.
66 + */
67 + constructor (size: number);
68 + /**
69 + * Allocates a new buffer containing the given {array} of octets.
70 + *
71 + * @param array The octets to store.
72 + */
73 + constructor (array: Uint8Array);
74 + /**
75 + * Produces a Buffer backed by the same allocated memory as
76 + * the given {ArrayBuffer}.
77 + *
78 + *
79 + * @param arrayBuffer The ArrayBuffer with which to share memory.
80 + */
81 + constructor (arrayBuffer: ArrayBuffer);
82 + /**
83 + * Allocates a new buffer containing the given {array} of octets.
84 + *
85 + * @param array The octets to store.
86 + */
87 + constructor (array: any[]);
88 + /**
89 + * Copies the passed {buffer} data onto a new {Buffer} instance.
90 + *
91 + * @param buffer The buffer to copy.
92 + */
93 + constructor (buffer: Buffer);
94 + prototype: Buffer;
95 + /**
96 + * Allocates a new Buffer using an {array} of octets.
97 + *
98 + * @param array
99 + */
100 + static from(array: any[]): Buffer;
101 + /**
102 + * When passed a reference to the .buffer property of a TypedArray instance,
103 + * the newly created Buffer will share the same allocated memory as the TypedArray.
104 + * The optional {byteOffset} and {length} arguments specify a memory range
105 + * within the {arrayBuffer} that will be shared by the Buffer.
106 + *
107 + * @param arrayBuffer The .buffer property of a TypedArray or a new ArrayBuffer()
108 + * @param byteOffset
109 + * @param length
110 + */
111 + static from(arrayBuffer: ArrayBuffer, byteOffset?: number, length?: number): Buffer;
112 + /**
113 + * Copies the passed {buffer} data onto a new Buffer instance.
114 + *
115 + * @param buffer
116 + */
117 + static from(buffer: Buffer): Buffer;
118 + /**
119 + * Creates a new Buffer containing the given JavaScript string {str}.
120 + * If provided, the {encoding} parameter identifies the character encoding.
121 + * If not provided, {encoding} defaults to 'utf8'.
122 + *
123 + * @param str
124 + */
125 + static from(str: string, encoding?: string): Buffer;
126 + /**
127 + * Returns true if {obj} is a Buffer
128 + *
129 + * @param obj object to test.
130 + */
131 + static isBuffer(obj: any): obj is Buffer;
132 + /**
133 + * Returns true if {encoding} is a valid encoding argument.
134 + * Valid string encodings in Node 0.12: 'ascii'|'utf8'|'utf16le'|'ucs2'(alias of 'utf16le')|'base64'|'binary'(deprecated)|'hex'
135 + *
136 + * @param encoding string to test.
137 + */
138 + static isEncoding(encoding: string): boolean;
139 + /**
140 + * Gives the actual byte length of a string. encoding defaults to 'utf8'.
141 + * This is not the same as String.prototype.length since that returns the number of characters in a string.
142 + *
143 + * @param string string to test.
144 + * @param encoding encoding used to evaluate (defaults to 'utf8')
145 + */
146 + static byteLength(string: string, encoding?: string): number;
147 + /**
148 + * Returns a buffer which is the result of concatenating all the buffers in the list together.
149 + *
150 + * If the list has no items, or if the totalLength is 0, then it returns a zero-length buffer.
151 + * If the list has exactly one item, then the first item of the list is returned.
152 + * If the list has more than one item, then a new Buffer is created.
153 + *
154 + * @param list An array of Buffer objects to concatenate
155 + * @param totalLength Total length of the buffers when concatenated.
156 + * If totalLength is not provided, it is read from the buffers in the list. However, this adds an additional loop to the function, so it is faster to provide the length explicitly.
157 + */
158 + static concat(list: Buffer[], totalLength?: number): Buffer;
159 + /**
160 + * The same as buf1.compare(buf2).
161 + */
162 + static compare(buf1: Buffer, buf2: Buffer): number;
163 + /**
164 + * Allocates a new buffer of {size} octets.
165 + *
166 + * @param size count of octets to allocate.
167 + * @param fill if specified, buffer will be initialized by calling buf.fill(fill).
168 + * If parameter is omitted, buffer will be filled with zeros.
169 + * @param encoding encoding used for call to buf.fill while initalizing
170 + */
171 + static alloc(size: number, fill?: string | Buffer | number, encoding?: string): Buffer;
172 + /**
173 + * Allocates a new buffer of {size} octets, leaving memory not initialized, so the contents
174 + * of the newly created Buffer are unknown and may contain sensitive data.
175 + *
176 + * @param size count of octets to allocate
177 + */
178 + static allocUnsafe(size: number): Buffer;
179 + /**
180 + * Allocates a new non-pooled buffer of {size} octets, leaving memory not initialized, so the contents
181 + * of the newly created Buffer are unknown and may contain sensitive data.
182 + *
183 + * @param size count of octets to allocate
184 + */
185 + static allocUnsafeSlow(size: number): Buffer;
186 + }
187 +}
...\ No newline at end of file ...\ No newline at end of file
1 +/*! safe-buffer. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
2 +/* eslint-disable node/no-deprecated-api */
3 +var buffer = require('buffer')
4 +var Buffer = buffer.Buffer
5 +
6 +// alternative to using Object.keys for old browsers
7 +function copyProps (src, dst) {
8 + for (var key in src) {
9 + dst[key] = src[key]
10 + }
11 +}
12 +if (Buffer.from && Buffer.alloc && Buffer.allocUnsafe && Buffer.allocUnsafeSlow) {
13 + module.exports = buffer
14 +} else {
15 + // Copy properties from require('buffer')
16 + copyProps(buffer, exports)
17 + exports.Buffer = SafeBuffer
18 +}
19 +
20 +function SafeBuffer (arg, encodingOrOffset, length) {
21 + return Buffer(arg, encodingOrOffset, length)
22 +}
23 +
24 +SafeBuffer.prototype = Object.create(Buffer.prototype)
25 +
26 +// Copy static methods from Buffer
27 +copyProps(Buffer, SafeBuffer)
28 +
29 +SafeBuffer.from = function (arg, encodingOrOffset, length) {
30 + if (typeof arg === 'number') {
31 + throw new TypeError('Argument must not be a number')
32 + }
33 + return Buffer(arg, encodingOrOffset, length)
34 +}
35 +
36 +SafeBuffer.alloc = function (size, fill, encoding) {
37 + if (typeof size !== 'number') {
38 + throw new TypeError('Argument must be a number')
39 + }
40 + var buf = Buffer(size)
41 + if (fill !== undefined) {
42 + if (typeof encoding === 'string') {
43 + buf.fill(fill, encoding)
44 + } else {
45 + buf.fill(fill)
46 + }
47 + } else {
48 + buf.fill(0)
49 + }
50 + return buf
51 +}
52 +
53 +SafeBuffer.allocUnsafe = function (size) {
54 + if (typeof size !== 'number') {
55 + throw new TypeError('Argument must be a number')
56 + }
57 + return Buffer(size)
58 +}
59 +
60 +SafeBuffer.allocUnsafeSlow = function (size) {
61 + if (typeof size !== 'number') {
62 + throw new TypeError('Argument must be a number')
63 + }
64 + return buffer.SlowBuffer(size)
65 +}
1 +{
2 + "name": "safe-buffer",
3 + "description": "Safer Node.js Buffer API",
4 + "version": "5.2.1",
5 + "author": {
6 + "name": "Feross Aboukhadijeh",
7 + "email": "feross@feross.org",
8 + "url": "https://feross.org"
9 + },
10 + "bugs": {
11 + "url": "https://github.com/feross/safe-buffer/issues"
12 + },
13 + "devDependencies": {
14 + "standard": "*",
15 + "tape": "^5.0.0"
16 + },
17 + "homepage": "https://github.com/feross/safe-buffer",
18 + "keywords": [
19 + "buffer",
20 + "buffer allocate",
21 + "node security",
22 + "safe",
23 + "safe-buffer",
24 + "security",
25 + "uninitialized"
26 + ],
27 + "license": "MIT",
28 + "main": "index.js",
29 + "types": "index.d.ts",
30 + "repository": {
31 + "type": "git",
32 + "url": "git://github.com/feross/safe-buffer.git"
33 + },
34 + "scripts": {
35 + "test": "standard && tape test/*.js"
36 + },
37 + "funding": [
38 + {
39 + "type": "github",
40 + "url": "https://github.com/sponsors/feross"
41 + },
42 + {
43 + "type": "patreon",
44 + "url": "https://www.patreon.com/feross"
45 + },
46 + {
47 + "type": "consulting",
48 + "url": "https://feross.org/support"
49 + }
50 + ]
51 +}
1 +'use strict';
2 +
3 +module.exports = function (req, time) {
4 + if (req.timeoutTimer) {
5 + return req;
6 + }
7 +
8 + var delays = isNaN(time) ? time : {socket: time, connect: time};
9 + var host = req._headers ? (' to ' + req._headers.host) : '';
10 +
11 + if (delays.connect !== undefined) {
12 + req.timeoutTimer = setTimeout(function timeoutHandler() {
13 + req.abort();
14 + var e = new Error('Connection timed out on request' + host);
15 + e.code = 'ETIMEDOUT';
16 + req.emit('error', e);
17 + }, delays.connect);
18 + }
19 +
20 + // Clear the connection timeout timer once a socket is assigned to the
21 + // request and is connected.
22 + req.on('socket', function assign(socket) {
23 + // Socket may come from Agent pool and may be already connected.
24 + if (!(socket.connecting || socket._connecting)) {
25 + connect();
26 + return;
27 + }
28 +
29 + socket.once('connect', connect);
30 + });
31 +
32 + function clear() {
33 + if (req.timeoutTimer) {
34 + clearTimeout(req.timeoutTimer);
35 + req.timeoutTimer = null;
36 + }
37 + }
38 +
39 + function connect() {
40 + clear();
41 +
42 + if (delays.socket !== undefined) {
43 + // Abort the request if there is no activity on the socket for more
44 + // than `delays.socket` milliseconds.
45 + req.setTimeout(delays.socket, function socketTimeoutHandler() {
46 + req.abort();
47 + var e = new Error('Socket timed out on request' + host);
48 + e.code = 'ESOCKETTIMEDOUT';
49 + req.emit('error', e);
50 + });
51 + }
52 + }
53 +
54 + return req.on('error', clear);
55 +};
1 +The MIT License (MIT)
2 +
3 +Copyright (c) Vsevolod Strukchinsky <floatdrop@gmail.com>
4 +
5 +Permission is hereby granted, free of charge, to any person obtaining a copy
6 +of this software and associated documentation files (the "Software"), to deal
7 +in the Software without restriction, including without limitation the rights
8 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 +copies of the Software, and to permit persons to whom the Software is
10 +furnished to do so, subject to the following conditions:
11 +
12 +The above copyright notice and this permission notice shall be included in
13 +all copies or substantial portions of the Software.
14 +
15 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 +THE SOFTWARE.
1 +{
2 + "name": "timed-out",
3 + "version": "4.0.1",
4 + "description": "Emit `ETIMEDOUT` or `ESOCKETTIMEDOUT` when ClientRequest is hanged",
5 + "license": "MIT",
6 + "repository": "floatdrop/timed-out",
7 + "author": {
8 + "name": "Vsevolod Strukchinsky",
9 + "email": "floatdrop@gmail.com"
10 + },
11 + "engines": {
12 + "node": ">=0.10.0"
13 + },
14 + "scripts": {
15 + "test": "xo && mocha"
16 + },
17 + "files": [
18 + "index.js"
19 + ],
20 + "keywords": [
21 + "http",
22 + "https",
23 + "get",
24 + "got",
25 + "url",
26 + "uri",
27 + "request",
28 + "util",
29 + "utility",
30 + "simple"
31 + ],
32 + "devDependencies": {
33 + "mocha": "*",
34 + "xo": "^0.16.0"
35 + }
36 +}
1 +# timed-out [![Build Status](https://travis-ci.org/floatdrop/timed-out.svg?branch=master)](https://travis-ci.org/floatdrop/timed-out)
2 +
3 +> Timeout HTTP/HTTPS requests
4 +
5 +Emit Error object with `code` property equal `ETIMEDOUT` or `ESOCKETTIMEDOUT` when ClientRequest is hanged.
6 +
7 +## Usage
8 +
9 +```js
10 +var get = require('http').get;
11 +var timeout = require('timed-out');
12 +
13 +var req = get('http://www.google.ru');
14 +timeout(req, 2000); // Set 2 seconds limit
15 +```
16 +
17 +### API
18 +
19 +#### timedout(request, time)
20 +
21 +##### request
22 +
23 +*Required*
24 +Type: [`ClientRequest`](http://nodejs.org/api/http.html#http_class_http_clientrequest)
25 +
26 +The request to watch on.
27 +
28 +##### time
29 +
30 +*Required*
31 +Type: `number` or `object`
32 +
33 +Time in milliseconds to wait for `connect` event on socket and also time to wait on inactive socket.
34 +
35 +Or you can pass Object with following fields:
36 +
37 +- `connect` - time to wait for connection
38 +- `socket` - time to wait for activity on socket
39 +
40 +## License
41 +
42 +MIT © [Vsevolod Strukchinsky](floatdrop@gmail.com)
1 +'use strict';
2 +var uniqueRandom = require('unique-random');
3 +
4 +module.exports = function (arr) {
5 + var rand = uniqueRandom(0, arr.length - 1);
6 +
7 + return function () {
8 + return arr[rand()];
9 + };
10 +};
1 +The MIT License (MIT)
2 +
3 +Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
4 +
5 +Permission is hereby granted, free of charge, to any person obtaining a copy
6 +of this software and associated documentation files (the "Software"), to deal
7 +in the Software without restriction, including without limitation the rights
8 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 +copies of the Software, and to permit persons to whom the Software is
10 +furnished to do so, subject to the following conditions:
11 +
12 +The above copyright notice and this permission notice shall be included in
13 +all copies or substantial portions of the Software.
14 +
15 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 +THE SOFTWARE.
1 +{
2 + "name": "unique-random-array",
3 + "version": "1.0.1",
4 + "description": "Get consecutively unique elements from an array",
5 + "keywords": [
6 + "unique",
7 + "uniq",
8 + "random",
9 + "rand",
10 + "number",
11 + "single",
12 + "generate",
13 + "non-repeating",
14 + "array",
15 + "arr",
16 + "item",
17 + "element"
18 + ],
19 + "license": "MIT",
20 + "author": {
21 + "name": "Sindre Sorhus",
22 + "email": "sindresorhus@gmail.com",
23 + "url": "sindresorhus.com"
24 + },
25 + "files": [
26 + "index.js"
27 + ],
28 + "repository": "sindresorhus/unique-random-array",
29 + "scripts": {
30 + "test": "ava"
31 + },
32 + "dependencies": {
33 + "unique-random": "^1.0.0"
34 + },
35 + "devDependencies": {
36 + "ava": "*"
37 + },
38 + "engines": {
39 + "node": ">=0.10.0"
40 + }
41 +}
1 +# unique-random-array [![Build Status](https://travis-ci.org/sindresorhus/unique-random-array.svg?branch=master)](https://travis-ci.org/sindresorhus/unique-random-array)
2 +
3 +> Get consecutively unique elements from an array
4 +
5 +Useful for things like slideshows where you don't want to have the same slide twice in a row.
6 +
7 +
8 +## Install
9 +
10 +```sh
11 +$ npm install --save unique-random-array
12 +```
13 +
14 +
15 +## Usage
16 +
17 +```js
18 +var uniqueRandomArray = require('unique-random-array');
19 +var rand = uniqueRandomArray([1, 2, 3, 4]);
20 +
21 +console.log(rand(), rand(), rand(), rand());
22 +//=> 4 2 1 4
23 +```
24 +
25 +
26 +## API
27 +
28 +### uniqueRandomArray(input)
29 +
30 +Returns a function that when called will return a random element that's never the same as the previous.
31 +
32 +#### input
33 +
34 +*Required*
35 +Type: `array`
36 +
37 +
38 +## Related
39 +
40 +- [unique-random](https://github.com/sindresorhus/unique-random) - Generate random numbers that are consecutively unique
41 +- [random-int](https://github.com/sindresorhus/random-int) - Generate a random integer
42 +- [random-float](https://github.com/sindresorhus/random-float) - Generate a random float
43 +- [random-item](https://github.com/sindresorhus/random-item) - Get a random item from an array
44 +- [random-obj-key](https://github.com/sindresorhus/random-obj-key) - Get a random key from an object
45 +- [random-obj-prop](https://github.com/sindresorhus/random-obj-prop) - Get a random property from an object
46 +- [crypto-random-string](https://github.com/sindresorhus/crypto-random-string) - Generate a cryptographically strong random string
47 +
48 +
49 +## License
50 +
51 +MIT © [Sindre Sorhus](http://sindresorhus.com)
1 +'use strict';
2 +module.exports = function (min, max) {
3 + var prev;
4 + return function rand() {
5 + var num = Math.floor(Math.random() * (max - min + 1) + min);
6 + return prev = num === prev && min !== max ? rand() : num;
7 + };
8 +};
1 +{
2 + "name": "unique-random",
3 + "version": "1.0.0",
4 + "description": "Generate random numbers that are consecutively unique",
5 + "keywords": [
6 + "unique",
7 + "random",
8 + "rand",
9 + "number",
10 + "single",
11 + "generate",
12 + "non-repeating"
13 + ],
14 + "license": "MIT",
15 + "author": {
16 + "name": "Sindre Sorhus",
17 + "email": "sindresorhus@gmail.com",
18 + "url": "http://sindresorhus.com"
19 + },
20 + "files": [
21 + "index.js"
22 + ],
23 + "repository": "sindresorhus/unique-random",
24 + "scripts": {
25 + "test": "mocha"
26 + },
27 + "devDependencies": {
28 + "mocha": "*"
29 + },
30 + "engines": {
31 + "node": ">=0.10.0"
32 + }
33 +}
1 +# unique-random [![Build Status](https://travis-ci.org/sindresorhus/unique-random.svg?branch=master)](https://travis-ci.org/sindresorhus/unique-random)
2 +
3 +> Generate random numbers that are consecutively unique.
4 +
5 +Useful for eg. slideshows where you don't want to have the same slide twice in a row.
6 +
7 +
8 +## Install
9 +
10 +```sh
11 +$ npm install --save unique-random
12 +```
13 +
14 +
15 +## Usage
16 +
17 +```js
18 +var rand = require('unique-random')(1, 10);
19 +console.log(rand(), rand(), rand());
20 +//=> 5 2 6
21 +```
22 +
23 +
24 +## API
25 +
26 +### uniqueRandom(*min*, *max*)
27 +
28 +Returns a function which when called will return a random number that's never the same as the previous number.
29 +
30 +
31 +## License
32 +
33 +MIT © [Sindre Sorhus](http://sindresorhus.com)
1 +'use strict';
2 +const PassThrough = require('stream').PassThrough;
3 +const zlib = require('zlib');
4 +
5 +module.exports = res => {
6 + // TODO: use Array#includes when targeting Node.js 6
7 + if (['gzip', 'deflate'].indexOf(res.headers['content-encoding']) === -1) {
8 + return res;
9 + }
10 +
11 + const unzip = zlib.createUnzip();
12 + const stream = new PassThrough();
13 +
14 + stream.httpVersion = res.httpVersion;
15 + stream.headers = res.headers;
16 + stream.rawHeaders = res.rawHeaders;
17 + stream.trailers = res.trailers;
18 + stream.rawTrailers = res.rawTrailers;
19 + stream.setTimeout = res.setTimeout.bind(res);
20 + stream.statusCode = res.statusCode;
21 + stream.statusMessage = res.statusMessage;
22 + stream.socket = res.socket;
23 +
24 + unzip.on('error', err => {
25 + if (err.code === 'Z_BUF_ERROR') {
26 + stream.end();
27 + return;
28 + }
29 +
30 + stream.emit('error', err);
31 + });
32 +
33 + res.pipe(unzip).pipe(stream);
34 +
35 + return stream;
36 +};
1 +`The MIT License (MIT)
2 +
3 +Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
4 +
5 +Permission is hereby granted, free of charge, to any person obtaining a copy
6 +of this software and associated documentation files (the "Software"), to deal
7 +in the Software without restriction, including without limitation the rights
8 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 +copies of the Software, and to permit persons to whom the Software is
10 +furnished to do so, subject to the following conditions:
11 +
12 +The above copyright notice and this permission notice shall be included in
13 +all copies or substantial portions of the Software.
14 +
15 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 +THE SOFTWARE.
1 +{
2 + "name": "unzip-response",
3 + "version": "2.0.1",
4 + "description": "Unzip a HTTP response if needed",
5 + "license": "MIT",
6 + "repository": "sindresorhus/unzip-response",
7 + "maintainers": [
8 + {
9 + "name": "Sindre Sorhus",
10 + "email": "sindresorhus@gmail.com",
11 + "url": "sindresorhus.com"
12 + },
13 + {
14 + "name": "Vsevolod Strukchinsky",
15 + "email": "floatdrop@gmail.com",
16 + "url": "github.com/floatdrop"
17 + }
18 + ],
19 + "engines": {
20 + "node": ">=4"
21 + },
22 + "scripts": {
23 + "test": "xo && ava"
24 + },
25 + "files": [
26 + "index.js"
27 + ],
28 + "keywords": [
29 + "http",
30 + "unzip",
31 + "zlib",
32 + "gzip",
33 + "deflate",
34 + "incoming",
35 + "message",
36 + "response",
37 + "stream"
38 + ],
39 + "devDependencies": {
40 + "ava": "*",
41 + "get-stream": "^2.3.0",
42 + "pify": "^2.3.0",
43 + "rfpify": "^1.0.0",
44 + "xo": "*"
45 + },
46 + "xo": {
47 + "esnext": true
48 + }
49 +}
1 +# unzip-response [![Build Status](https://travis-ci.org/sindresorhus/unzip-response.svg?branch=master)](https://travis-ci.org/sindresorhus/unzip-response)
2 +
3 +> Unzip a HTTP response if needed
4 +
5 +Unzips the response from [`http.request`](https://nodejs.org/api/http.html#http_http_request_options_callback) if it's gzipped/deflated, otherwise just passes it through.
6 +
7 +
8 +## Install
9 +
10 +```
11 +$ npm install --save unzip-response
12 +```
13 +
14 +
15 +## Usage
16 +
17 +```js
18 +const http = require('http');
19 +const unzipResponse = require('unzip-response');
20 +
21 +http.get('http://sindresorhus.com', res => {
22 + res = unzipResponse(res);
23 +});
24 +```
25 +
26 +
27 +## License
28 +
29 +MIT © [Sindre Sorhus](https://sindresorhus.com)
1 +'use strict';
2 +var url = require('url');
3 +var prependHttp = require('prepend-http');
4 +
5 +module.exports = function (x) {
6 + var withProtocol = prependHttp(x);
7 + var parsed = url.parse(withProtocol);
8 +
9 + if (withProtocol !== x) {
10 + parsed.protocol = null;
11 + }
12 +
13 + return parsed;
14 +};
1 +The MIT License (MIT)
2 +
3 +Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
4 +
5 +Permission is hereby granted, free of charge, to any person obtaining a copy
6 +of this software and associated documentation files (the "Software"), to deal
7 +in the Software without restriction, including without limitation the rights
8 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 +copies of the Software, and to permit persons to whom the Software is
10 +furnished to do so, subject to the following conditions:
11 +
12 +The above copyright notice and this permission notice shall be included in
13 +all copies or substantial portions of the Software.
14 +
15 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 +THE SOFTWARE.
1 +{
2 + "name": "url-parse-lax",
3 + "version": "1.0.0",
4 + "description": "url.parse() with support for protocol-less URLs & IPs",
5 + "license": "MIT",
6 + "repository": "sindresorhus/url-parse-lax",
7 + "author": {
8 + "name": "Sindre Sorhus",
9 + "email": "sindresorhus@gmail.com",
10 + "url": "sindresorhus.com"
11 + },
12 + "engines": {
13 + "node": ">=0.10.0"
14 + },
15 + "scripts": {
16 + "test": "node test.js"
17 + },
18 + "files": [
19 + "index.js"
20 + ],
21 + "keywords": [
22 + "url",
23 + "uri",
24 + "parse",
25 + "parser",
26 + "loose",
27 + "lax",
28 + "protocol",
29 + "less",
30 + "protocol-less",
31 + "ip",
32 + "ipv4",
33 + "ipv6"
34 + ],
35 + "dependencies": {
36 + "prepend-http": "^1.0.1"
37 + },
38 + "devDependencies": {
39 + "ava": "0.0.4"
40 + }
41 +}
1 +# url-parse-lax [![Build Status](https://travis-ci.org/sindresorhus/url-parse-lax.svg?branch=master)](https://travis-ci.org/sindresorhus/url-parse-lax)
2 +
3 +> [`url.parse()`](https://nodejs.org/docs/latest/api/url.html#url_url_parse_urlstr_parsequerystring_slashesdenotehost) with support for protocol-less URLs & IPs
4 +
5 +
6 +## Install
7 +
8 +```
9 +$ npm install --save url-parse-lax
10 +```
11 +
12 +
13 +## Usage
14 +
15 +```js
16 +var urlParseLax = require('url-parse-lax');
17 +
18 +urlParseLax('sindresorhus.com');
19 +/*
20 +{
21 + protocol: null,
22 + slashes: true,
23 + auth: null,
24 + host: 'sindresorhus.com',
25 + port: null,
26 + hostname: 'sindresorhus.com',
27 + hash: null,
28 + search: null,
29 + query: null,
30 + pathname: '/',
31 + path: '/',
32 + href: 'http://sindresorhus.com/'
33 +}
34 +*/
35 +
36 +urlParseLax('[2001:db8::]:8000');
37 +/*
38 +{
39 + protocol: null,
40 + slashes: true,
41 + auth: null,
42 + host: '[2001:db8::]:8000',
43 + port: '8000',
44 + hostname: '2001:db8::',
45 + hash: null,
46 + search: null,
47 + query: null,
48 + pathname: '/',
49 + path: '/',
50 + href: 'http://[2001:db8::]:8000/'
51 +}
52 +*/
53 +```
54 +
55 +And with the built-in `url.parse()`:
56 +
57 +```js
58 +var url = require('url');
59 +
60 +url.parse('sindresorhus.com');
61 +/*
62 +{
63 + protocol: null,
64 + slashes: null,
65 + auth: null,
66 + host: null,
67 + port: null,
68 + hostname: null,
69 + hash: null,
70 + search: null,
71 + query: null,
72 + pathname: 'sindresorhus',
73 + path: 'sindresorhus',
74 + href: 'sindresorhus'
75 +}
76 +*/
77 +
78 +url.parse('[2001:db8::]:8000');
79 +/*
80 +{
81 + protocol: null,
82 + slashes: null,
83 + auth: null,
84 + host: null,
85 + port: null,
86 + hostname: null,
87 + hash: null,
88 + search: null,
89 + query: null,
90 + pathname: '[2001:db8::]:8000',
91 + path: '[2001:db8::]:8000',
92 + href: '[2001:db8::]:8000'
93 +}
94 +*/
95 +```
96 +
97 +
98 +## License
99 +
100 +MIT © [Sindre Sorhus](http://sindresorhus.com)