rekwest 4.1.0 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,187 +1,188 @@
1
- The robust request library that humanity deserves 🌐
2
- ---
3
- This package provides highly likely functional and **easy-to-use** abstraction atop of
4
- native [http(s).request](https://nodejs.org/api/https.html#https_https_request_url_options_callback)
5
- and [http2.request](https://nodejs.org/api/http2.html#http2_clienthttp2session_request_headers_options).
6
-
7
- ## Abstract
8
-
9
- * Fetch-alike
10
- * Cool-beans 🫐 config options (with defaults)
11
- * Automatic HTTP/2 support (ALPN negotiation)
12
- * Automatic or opt-in body parse (with non-UTF-8 charset decoding)
13
- * Automatic and simplistic `Cookies` treatment (with built-in jar)
14
- * Automatic decompression (with opt-in body compression)
15
- * Built-in streamable `File` & `FormData` interfaces
16
- * Support redirects & retries with fine-grained tune-ups
17
- * Support all legit request body types (include blobs & streams)
18
- * Support both CJS and ESM module systems
19
- * Fully promise-able and pipe-able
20
- * Zero dependencies
21
-
22
- ## Prerequisites
23
-
24
- * Node.js `>= 16.7.x`
25
-
26
- ## Installation
27
-
28
- ```bash
29
- npm install rekwest --save
30
- ```
31
-
32
- ### Usage
33
-
34
- ```javascript
35
- import rekwest, { constants } from 'rekwest';
36
-
37
- const {
38
- HTTP2_HEADER_AUTHORIZATION,
39
- HTTP2_HEADER_CONTENT_ENCODING,
40
- HTTP2_METHOD_POST,
41
- HTTP_STATUS_OK,
42
- } = constants;
43
-
44
- const url = 'https://somewhe.re/somewhat/endpoint';
45
-
46
- const res = await rekwest(url, {
47
- body: { celestial: 'payload' },
48
- headers: {
49
- [HTTP2_HEADER_AUTHORIZATION]: 'Bearer [token]',
50
- [HTTP2_HEADER_CONTENT_ENCODING]: 'br', // enables: body compression
51
- /** [HTTP2_HEADER_CONTENT_TYPE]
52
- * is undue for
53
- * Array/Blob/File/FormData/Object/URLSearchParams body types
54
- * and will be set automatically, with an option to override it here
55
- */
56
- },
57
- method: HTTP2_METHOD_POST,
58
- });
59
-
60
- console.assert(res.statusCode === HTTP_STATUS_OK);
61
- console.info(res.headers);
62
- console.log(res.body);
63
- ```
64
-
65
- ---
66
-
67
- ```javascript
68
- import rekwest, {
69
- constants,
70
- Blob,
71
- File,
72
- FormData,
73
- } from 'rekwest';
74
- import { Readable } from 'node:stream';
75
-
76
- const {
77
- HTTP2_HEADER_AUTHORIZATION,
78
- HTTP2_HEADER_CONTENT_ENCODING,
79
- HTTP2_METHOD_POST,
80
- HTTP_STATUS_OK,
81
- } = constants;
82
-
83
- const blob = new Blob(['bits']);
84
- const file = new File(['bits'], 'file.dab');
85
- const readable = Readable.from('bits');
86
-
87
- const fd = new FormData({
88
- aux: Date.now(), // either [[key, value]], or kv sequenceable
89
- });
90
-
91
- fd.append('celestial', 'payload');
92
- fd.append('blob', blob, 'blob.dab');
93
- fd.append('file', file);
94
- fd.append('readable', readable, 'readable.dab');
95
-
96
- const url = 'https://somewhe.re/somewhat/endpoint';
97
-
98
- const res = await rekwest(url, {
99
- body: fd,
100
- headers: {
101
- [HTTP2_HEADER_AUTHORIZATION]: 'Bearer [token]',
102
- [HTTP2_HEADER_CONTENT_ENCODING]: 'br', // enables: body compression
103
- },
104
- method: HTTP2_METHOD_POST,
105
- });
106
-
107
- console.assert(res.statusCode === HTTP_STATUS_OK);
108
- console.info(res.headers);
109
- console.log(res.body);
110
- ```
111
-
112
- ### API
113
-
114
- #### `rekwest(url[, options])`
115
-
116
- * `url` **{string | URL}** The URL to send the request to
117
- * `options` **{Object}**
118
- Extends [https.RequestOptions](https://nodejs.org/api/https.html#https_https_request_url_options_callback)
119
- along with
120
- extra [http2.ClientSessionOptions](https://nodejs.org/api/http2.html#http2_http2_connect_authority_options_listener)
121
- & [http2.ClientSessionRequestOptions](https://nodejs.org/api/http2.html#http2_clienthttp2session_request_headers_options)
122
- and [tls.ConnectionOptions](https://nodejs.org/api/tls.html#tls_tls_connect_options_callback)
123
- for HTTP/2 attunes
124
- * `body` **{string | Array | ArrayBuffer | ArrayBufferView | AsyncIterator | Blob | Buffer | DataView | File |
125
- FormData | Iterator | Object | Readable | ReadableStream | SharedArrayBuffer | URLSearchParams}** The body to send
126
- with the request
127
- * `cookies` **{boolean | Array<[k, v]> | Cookies | Object | URLSearchParams}** `Default: true` The cookies to add to
128
- the request
129
- * `digest` **{boolean}** `Default: true` Controls whether to read the response stream or simply add a mixin
130
- * `follow` **{number}** `Default: 20` The number of redirects to follow
131
- * `h2` **{boolean}** `Default: false` Forces the use of HTTP/2 protocol
132
- * `headers` **{Object}** The headers to add to the request
133
- * `maxRetryAfter` **{number}** The upper limit of `retry-after` header. If unset, it will use `timeout` value
134
- * `parse` **{boolean}** `Default: true` Controls whether to parse response body or simply return a buffer
135
- * `redirect` **{error | follow | manual}** `Default: follow` Controls the redirect flows
136
- * `retry` **{Object}** Represents the retry options
137
- * `attempts` **{number}** `Default: 0` The number of retry attempts
138
- * `backoffStrategy` **{string}** `Default: interval * Math.log(Math.random() * (Math.E * Math.E - Math.E) + Math.E)`
139
- The backoff strategy algorithm that increases logarithmically. To fixate set value to `interval * 1`
140
- * `interval` **{number}** `Default: 1e3` The initial retry interval
141
- * `retryAfter` **{boolean}** `Default: true` Controls `retry-after` header receptiveness
142
- * `statusCodes` **{number[]}** `Default: [429, 503]` The list of status codes to retry on
143
- * `thenable` **{boolean}** `Default: false` Controls the promise resolutions
144
- * `timeout` **{number}** `Default: 3e5` The number of milliseconds a request can take before termination
145
- * `trimTrailingSlashes` **{boolean}** `Default: false` Controls whether to trim trailing slashes in the URL before
146
- proceed with the request
147
- * **Returns:** Promise that resolves to
148
- extended [http.IncomingMessage](https://nodejs.org/api/http.html#http_class_http_incomingmessage)
149
- or [http2.ClientHttp2Stream](https://nodejs.org/api/http2.html#http2_class_clienthttp2stream) which is respectively
150
- readable and duplex streams
151
- * if `degist: true` & `parse: true`
152
- * `body` **{string | Array | Buffer | Object}** The body based on its content type
153
- * if `degist: false`
154
- * `arrayBuffer` **{AsyncFunction}** Reads the response and returns **ArrayBuffer**
155
- * `blob` **{AsyncFunction}** Reads the response and returns **Blob**
156
- * `body` **{AsyncFunction}** Reads the response and returns **Buffer** if `parse: false`
157
- * `json` **{AsyncFunction}** Reads the response and returns **Object**
158
- * `text` **{AsyncFunction}** Reads the response and returns **String**
159
- * `bodyUsed` **{boolean}** Indicates whether the response were read or not
160
- * `cookies` **{undefined | Cookies}** The cookies sent and received with the response
161
- * `headers` **{Object}** The headers received with the response
162
- * `httpVersion` **{string}** Indicates protocol version negotiated with the server
163
- * `ok` **{boolean}** Indicates if the response was successful (statusCode: **200-299**)
164
- * `redirected` **{boolean}** Indicates if the response is the result of a redirect
165
- * `statusCode` **{number}** Indicates the status code of the response
166
- * `trailers` **{undefined | Object}** The trailer headers received with the response
167
-
168
- ---
169
-
170
- #### `rekwest.defaults`
171
-
172
- The object to fulfill with default [options](#rekwesturl-options)
173
-
174
- ---
175
-
176
- #### `rekwest.stream(url[, options])`
177
-
178
- The method with limited functionality to use with streams and/or pipes
179
-
180
- * No automata
181
- * No redirects
182
- * Pass `h2: true` in options to use HTTP/2 protocol
183
- * Use `ackn({ url: URL })` method beforehand to check the available protocols
184
-
185
- ---
186
-
187
- For more details, please check tests (coverage: **>97%**) in the repository
1
+ The robust request library that humanity deserves 🌐
2
+ ---
3
+ This package provides highly likely functional and **easy-to-use** abstraction atop of
4
+ native [http(s).request](https://nodejs.org/api/https.html#https_https_request_url_options_callback)
5
+ and [http2.request](https://nodejs.org/api/http2.html#http2_clienthttp2session_request_headers_options).
6
+
7
+ ## Abstract
8
+
9
+ * Fetch-alike
10
+ * Cool-beans 🫐 config options (with defaults)
11
+ * Automatic HTTP/2 support (ALPN negotiation)
12
+ * Automatic or opt-in body parse (with non-UTF-8 charset decoding)
13
+ * Automatic and simplistic `Cookies` treatment (with built-in jar)
14
+ * Automatic decompression (with opt-in body compression)
15
+ * Built-in streamable `File` & `FormData` interfaces
16
+ * Support redirects & retries with fine-grained tune-ups
17
+ * Support all legit request body types (include blobs & streams)
18
+ * Support both CJS and ESM module systems
19
+ * Fully promise-able and pipe-able
20
+ * Zero dependencies
21
+
22
+ ## Prerequisites
23
+
24
+ * Node.js `>= 16.7.x`
25
+
26
+ ## Installation
27
+
28
+ ```bash
29
+ npm install rekwest --save
30
+ ```
31
+
32
+ ### Usage
33
+
34
+ ```javascript
35
+ import rekwest, { constants } from 'rekwest';
36
+
37
+ const {
38
+ HTTP2_HEADER_AUTHORIZATION,
39
+ HTTP2_HEADER_CONTENT_ENCODING,
40
+ HTTP2_METHOD_POST,
41
+ HTTP_STATUS_OK,
42
+ } = constants;
43
+
44
+ const url = 'https://somewhe.re/somewhat/endpoint';
45
+
46
+ const res = await rekwest(url, {
47
+ body: { celestial: 'payload' },
48
+ headers: {
49
+ [HTTP2_HEADER_AUTHORIZATION]: 'Bearer [token]',
50
+ [HTTP2_HEADER_CONTENT_ENCODING]: 'br', // enables: body compression
51
+ /** [HTTP2_HEADER_CONTENT_TYPE]
52
+ * is undue for
53
+ * Array/Blob/File/FormData/Object/URLSearchParams body types
54
+ * and will be set automatically, with an option to override it here
55
+ */
56
+ },
57
+ method: HTTP2_METHOD_POST,
58
+ });
59
+
60
+ console.assert(res.statusCode === HTTP_STATUS_OK);
61
+ console.info(res.headers);
62
+ console.log(res.body);
63
+ ```
64
+
65
+ ---
66
+
67
+ ```javascript
68
+ import rekwest, {
69
+ constants,
70
+ Blob,
71
+ File,
72
+ FormData,
73
+ } from 'rekwest';
74
+ import { Readable } from 'node:stream';
75
+
76
+ const {
77
+ HTTP2_HEADER_AUTHORIZATION,
78
+ HTTP2_HEADER_CONTENT_ENCODING,
79
+ HTTP2_METHOD_POST,
80
+ HTTP_STATUS_OK,
81
+ } = constants;
82
+
83
+ const blob = new Blob(['bits']);
84
+ const file = new File(['bits'], 'file.dab');
85
+ const readable = Readable.from('bits');
86
+
87
+ const fd = new FormData({
88
+ aux: Date.now(), // either [[key, value]] or kv sequenceable
89
+ });
90
+
91
+ fd.append('celestial', 'payload');
92
+ fd.append('blob', blob, 'blob.dab');
93
+ fd.append('file', file);
94
+ fd.append('readable', readable, 'readable.dab');
95
+
96
+ const url = 'https://somewhe.re/somewhat/endpoint';
97
+
98
+ const res = await rekwest(url, {
99
+ body: fd,
100
+ headers: {
101
+ [HTTP2_HEADER_AUTHORIZATION]: 'Bearer [token]',
102
+ [HTTP2_HEADER_CONTENT_ENCODING]: 'br', // enables: body compression
103
+ },
104
+ method: HTTP2_METHOD_POST,
105
+ });
106
+
107
+ console.assert(res.statusCode === HTTP_STATUS_OK);
108
+ console.info(res.headers);
109
+ console.log(res.body);
110
+ ```
111
+
112
+ ### API
113
+
114
+ #### `rekwest(url[, options])`
115
+
116
+ * `url` **{string | URL}** The URL to send the request to
117
+ * `options` **{Object}**
118
+ Extends [https.RequestOptions](https://nodejs.org/api/https.html#https_https_request_url_options_callback)
119
+ along with
120
+ extra [http2.ClientSessionOptions](https://nodejs.org/api/http2.html#http2_http2_connect_authority_options_listener)
121
+ & [http2.ClientSessionRequestOptions](https://nodejs.org/api/http2.html#http2_clienthttp2session_request_headers_options)
122
+ and [tls.ConnectionOptions](https://nodejs.org/api/tls.html#tls_tls_connect_options_callback)
123
+ for HTTP/2 attunes
124
+ * `body` **{string | Array | ArrayBuffer | ArrayBufferView | AsyncIterator | Blob | Buffer | DataView | File |
125
+ FormData | Iterator | Object | Readable | SharedArrayBuffer | URLSearchParams}** The body to send with the request
126
+ * `cookies` **{boolean | Array<[k, v]> | Cookies | Object | URLSearchParams}** `Default: true` The cookies to add to
127
+ the request
128
+ * `credentials` **{include | omit | same-origin}** `Default: same-origin` Controls credentials in case of cross-origin
129
+ redirects
130
+ * `digest` **{boolean}** `Default: true` Controls whether to read the response stream or simply add a mixin
131
+ * `follow` **{number}** `Default: 20` The number of redirects to follow
132
+ * `h2` **{boolean}** `Default: false` Forces the use of HTTP/2 protocol
133
+ * `headers` **{Object}** The headers to add to the request
134
+ * `maxRetryAfter` **{number}** The upper limit of `retry-after` header. If unset, it will use `timeout` value
135
+ * `parse` **{boolean}** `Default: true` Controls whether to parse response body or simply return a buffer
136
+ * `redirect` **{error | follow | manual}** `Default: follow` Controls the redirect flows
137
+ * `retry` **{Object}** Represents the retry options
138
+ * `attempts` **{number}** `Default: 0` The number of retry attempts
139
+ * `backoffStrategy` **{string}** `Default: interval * Math.log(Math.random() * (Math.E * Math.E - Math.E) + Math.E)`
140
+ The backoff strategy algorithm that increases logarithmically. To fixate set value to `interval * 1`
141
+ * `interval` **{number}** `Default: 1e3` The initial retry interval
142
+ * `retryAfter` **{boolean}** `Default: true` Controls `retry-after` header receptiveness
143
+ * `statusCodes` **{number[]}** `Default: [429, 503]` The list of status codes to retry on
144
+ * `thenable` **{boolean}** `Default: false` Controls the promise resolutions
145
+ * `timeout` **{number}** `Default: 3e5` The number of milliseconds a request can take before termination
146
+ * `trimTrailingSlashes` **{boolean}** `Default: false` Controls whether to trim trailing slashes in the URL before
147
+ proceed with the request
148
+ * **Returns:** Promise that resolves to
149
+ extended [http.IncomingMessage](https://nodejs.org/api/http.html#http_class_http_incomingmessage)
150
+ or [http2.ClientHttp2Stream](https://nodejs.org/api/http2.html#http2_class_clienthttp2stream) which is respectively
151
+ readable and duplex streams
152
+ * if `degist: true` & `parse: true`
153
+ * `body` **{string | Array | Buffer | Object}** The body based on its content type
154
+ * if `degist: false`
155
+ * `arrayBuffer` **{AsyncFunction}** Reads the response and returns **ArrayBuffer**
156
+ * `blob` **{AsyncFunction}** Reads the response and returns **Blob**
157
+ * `body` **{AsyncFunction}** Reads the response and returns **Buffer** if `parse: false`
158
+ * `json` **{AsyncFunction}** Reads the response and returns **Object**
159
+ * `text` **{AsyncFunction}** Reads the response and returns **String**
160
+ * `bodyUsed` **{boolean}** Indicates whether the response were read or not
161
+ * `cookies` **{undefined | Cookies}** The cookies sent and received with the response
162
+ * `headers` **{Object}** The headers received with the response
163
+ * `httpVersion` **{string}** Indicates protocol version negotiated with the server
164
+ * `ok` **{boolean}** Indicates if the response was successful (statusCode: **200-299**)
165
+ * `redirected` **{boolean}** Indicates if the response is the result of a redirect
166
+ * `statusCode` **{number}** Indicates the status code of the response
167
+ * `trailers` **{undefined | Object}** The trailer headers received with the response
168
+
169
+ ---
170
+
171
+ #### `rekwest.defaults`
172
+
173
+ The object to fulfill with default [options](#rekwesturl-options)
174
+
175
+ ---
176
+
177
+ #### `rekwest.stream(url[, options])`
178
+
179
+ The method with limited functionality to use with streams and/or pipes
180
+
181
+ * No automata
182
+ * No redirects
183
+ * Pass `h2: true` in options to use HTTP/2 protocol
184
+ * Use `ackn({ url: URL })` method beforehand to check the available protocols
185
+
186
+ ---
187
+
188
+ For more details, please check tests (coverage: **>97%**) in the repository
package/dist/ackn.js CHANGED
@@ -25,7 +25,7 @@ const ackn = options => new Promise((resolve, reject) => {
25
25
  createConnection() {
26
26
  return socket;
27
27
  },
28
- h2: /h2c?/.test(alpnProtocol),
28
+ h2: /h2c?/i.test(alpnProtocol),
29
29
  protocol: url.protocol
30
30
  });
31
31
  });
package/dist/constants.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
 
3
3
  exports.__esModule = true;
4
- exports.redirectStatusCodes = exports.redirectModes = void 0;
4
+ exports.requestRedirectCodes = exports.requestRedirect = exports.requestCredentials = void 0;
5
5
  var _nodeHttp = _interopRequireDefault(require("node:http2"));
6
6
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
7
7
  const {
@@ -11,11 +11,17 @@ const {
11
11
  HTTP_STATUS_SEE_OTHER,
12
12
  HTTP_STATUS_TEMPORARY_REDIRECT
13
13
  } = _nodeHttp.default.constants;
14
- const redirectModes = {
14
+ const requestCredentials = {
15
+ include: 'include',
16
+ omit: 'omit',
17
+ sameOrigin: 'same-origin'
18
+ };
19
+ exports.requestCredentials = requestCredentials;
20
+ const requestRedirect = {
15
21
  error: 'error',
16
22
  follow: 'follow',
17
23
  manual: 'manual'
18
24
  };
19
- exports.redirectModes = redirectModes;
20
- const redirectStatusCodes = [HTTP_STATUS_MOVED_PERMANENTLY, HTTP_STATUS_FOUND, HTTP_STATUS_SEE_OTHER, HTTP_STATUS_TEMPORARY_REDIRECT, HTTP_STATUS_PERMANENT_REDIRECT];
21
- exports.redirectStatusCodes = redirectStatusCodes;
25
+ exports.requestRedirect = requestRedirect;
26
+ const requestRedirectCodes = [HTTP_STATUS_MOVED_PERMANENTLY, HTTP_STATUS_FOUND, HTTP_STATUS_SEE_OTHER, HTTP_STATUS_TEMPORARY_REDIRECT, HTTP_STATUS_PERMANENT_REDIRECT];
27
+ exports.requestRedirectCodes = requestRedirectCodes;
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.default = void 0;
5
+ var _nodeHttp = _interopRequireDefault(require("node:http2"));
6
+ var _constants = require("./constants");
7
+ var _utils = require("./utils");
8
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
9
+ const {
10
+ HTTP2_METHOD_GET,
11
+ HTTP_STATUS_SERVICE_UNAVAILABLE,
12
+ HTTP_STATUS_TOO_MANY_REQUESTS
13
+ } = _nodeHttp.default.constants;
14
+ const stash = {
15
+ credentials: _constants.requestCredentials.sameOrigin,
16
+ digest: true,
17
+ follow: 20,
18
+ get maxRetryAfter() {
19
+ return this[_utils.maxRetryAfter] ?? this.timeout;
20
+ },
21
+ set maxRetryAfter(value) {
22
+ this[_utils.maxRetryAfter] = value;
23
+ },
24
+ method: HTTP2_METHOD_GET,
25
+ parse: true,
26
+ redirect: _constants.requestRedirect.follow,
27
+ redirected: false,
28
+ retry: {
29
+ attempts: 0,
30
+ backoffStrategy: 'interval * Math.log(Math.random() * (Math.E * Math.E - Math.E) + Math.E)',
31
+ interval: 1e3,
32
+ retryAfter: true,
33
+ statusCodes: [HTTP_STATUS_TOO_MANY_REQUESTS, HTTP_STATUS_SERVICE_UNAVAILABLE]
34
+ },
35
+ thenable: false,
36
+ timeout: 3e5
37
+ };
38
+ var _default = {
39
+ stash
40
+ };
41
+ exports.default = _default;