rekwest 4.2.2 → 4.3.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
@@ -121,6 +121,7 @@ console.log(res.body);
121
121
  & [http2.ClientSessionRequestOptions](https://nodejs.org/api/http2.html#http2_clienthttp2session_request_headers_options)
122
122
  and [tls.ConnectionOptions](https://nodejs.org/api/tls.html#tls_tls_connect_options_callback)
123
123
  for HTTP/2 attunes
124
+ * `baseURL` **{string | URL}** The base URL to use in cases where `url` is a relative URL
124
125
  * `body` **{string | Array | ArrayBuffer | ArrayBufferView | AsyncIterator | Blob | Buffer | DataView | File |
125
126
  FormData | Iterator | Object | Readable | SharedArrayBuffer | URLSearchParams}** The body to send with the request
126
127
  * `cookies` **{boolean | Array<[k, v]> | Cookies | Object | URLSearchParams}** `Default: true` The cookies to add to
package/dist/formdata.js CHANGED
@@ -20,16 +20,16 @@ class FormData {
20
20
  const contentType = `${_mediatypes.MULTIPART_FORM_DATA}; boundary=${boundary}`;
21
21
  const prefix = `--${boundary}${CRLF}${HTTP2_HEADER_CONTENT_DISPOSITION}: form-data`;
22
22
  const escape = str => str.replace(/\n/g, '%0A').replace(/\r/g, '%0D').replace(/"/g, '%22');
23
- const normalize = value => value.replace(/\r?\n|\r/g, CRLF);
23
+ const redress = value => value.replace(/\r?\n|\r/g, CRLF);
24
24
  return {
25
25
  contentType,
26
26
  async *[Symbol.asyncIterator]() {
27
27
  const encoder = new TextEncoder();
28
28
  for (const [name, value] of fd) {
29
29
  if (value.constructor === String) {
30
- yield encoder.encode(`${prefix}; name="${escape(normalize(name))}"${CRLF.repeat(2)}${normalize(value)}${CRLF}`);
30
+ yield encoder.encode(`${prefix}; name="${escape(redress(name))}"${CRLF.repeat(2)}${redress(value)}${CRLF}`);
31
31
  } else {
32
- yield encoder.encode(`${prefix}; name="${escape(normalize(name))}"${value.name ? `; filename="${escape(value.name)}"` : ''}${CRLF}${HTTP2_HEADER_CONTENT_TYPE}: ${value.type || _mediatypes.APPLICATION_OCTET_STREAM}${CRLF.repeat(2)}`);
32
+ yield encoder.encode(`${prefix}; name="${escape(redress(name))}"${value.name ? `; filename="${escape(value.name)}"` : ''}${CRLF}${HTTP2_HEADER_CONTENT_TYPE}: ${value.type || _mediatypes.APPLICATION_OCTET_STREAM}${CRLF.repeat(2)}`);
33
33
  yield* (0, _utils.tap)(value);
34
34
  yield new Uint8Array([13, 10]);
35
35
  }
package/dist/index.js CHANGED
@@ -30,6 +30,13 @@ Object.keys(_utils).forEach(function (key) {
30
30
  if (key in exports && exports[key] === _utils[key]) return;
31
31
  exports[key] = _utils[key];
32
32
  });
33
+ var _validation = require("./validation");
34
+ Object.keys(_validation).forEach(function (key) {
35
+ if (key === "default" || key === "__esModule") return;
36
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
37
+ if (key in exports && exports[key] === _validation[key]) return;
38
+ exports[key] = _validation[key];
39
+ });
33
40
  var _ackn = require("./ackn");
34
41
  Object.keys(_ackn).forEach(function (key) {
35
42
  if (key === "default" || key === "__esModule") return;
@@ -65,6 +72,13 @@ Object.keys(_formdata).forEach(function (key) {
65
72
  if (key in exports && exports[key] === _formdata[key]) return;
66
73
  exports[key] = _formdata[key];
67
74
  });
75
+ var _mixin = require("./mixin");
76
+ Object.keys(_mixin).forEach(function (key) {
77
+ if (key === "default" || key === "__esModule") return;
78
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
79
+ if (key in exports && exports[key] === _mixin[key]) return;
80
+ exports[key] = _mixin[key];
81
+ });
68
82
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
69
83
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
70
84
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@@ -72,21 +86,21 @@ const {
72
86
  HTTP2_HEADER_CONTENT_TYPE
73
87
  } = _nodeHttp2.default.constants;
74
88
  function rekwest(...args) {
75
- let options = (0, _utils.sanitize)(...args);
89
+ let options = (0, _utils.normalize)(...args);
76
90
  if (!options.redirected) {
77
91
  options = (0, _utils.merge)(rekwest.defaults, options);
78
92
  }
79
- return (0, _utils.transfer)((0, _utils.validation)(options));
93
+ return (0, _utils.transfer)((0, _validation.validation)(options));
80
94
  }
81
95
  Reflect.defineProperty(rekwest, 'stream', {
82
96
  enumerable: true,
83
97
  value(...args) {
84
98
  const options = (0, _preflight.preflight)({
85
- ...(0, _utils.validation)((0, _utils.merge)(rekwest.defaults, {
99
+ ...(0, _validation.validation)((0, _utils.merge)(rekwest.defaults, {
86
100
  headers: {
87
101
  [HTTP2_HEADER_CONTENT_TYPE]: _mediatypes.APPLICATION_OCTET_STREAM
88
102
  }
89
- }, (0, _utils.sanitize)(...args))),
103
+ }, (0, _utils.normalize)(...args))),
90
104
  redirect: _constants.requestRedirect.manual
91
105
  });
92
106
  const {
package/dist/mixin.js ADDED
@@ -0,0 +1,99 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.mixin = void 0;
5
+ var _nodeBuffer = require("node:buffer");
6
+ var _nodeHttp = _interopRequireDefault(require("node:http2"));
7
+ var _utils = require("./utils");
8
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
9
+ const {
10
+ HTTP2_HEADER_CONTENT_ENCODING,
11
+ HTTP2_HEADER_CONTENT_TYPE
12
+ } = _nodeHttp.default.constants;
13
+ const mixin = (res, {
14
+ digest = false,
15
+ parse = false
16
+ } = {}) => {
17
+ if (!digest) {
18
+ Object.defineProperties(res, {
19
+ arrayBuffer: {
20
+ enumerable: true,
21
+ value: async function () {
22
+ (0, _utils.brandCheck)(this, res?.constructor);
23
+ parse &&= false;
24
+ const {
25
+ buffer,
26
+ byteLength,
27
+ byteOffset
28
+ } = await this.body();
29
+ return buffer.slice(byteOffset, byteOffset + byteLength);
30
+ }
31
+ },
32
+ blob: {
33
+ enumerable: true,
34
+ value: async function () {
35
+ (0, _utils.brandCheck)(this, res?.constructor);
36
+ const val = await this.arrayBuffer();
37
+ return new _nodeBuffer.Blob([val]);
38
+ }
39
+ },
40
+ json: {
41
+ enumerable: true,
42
+ value: async function () {
43
+ (0, _utils.brandCheck)(this, res?.constructor);
44
+ const val = await this.text();
45
+ return JSON.parse(val);
46
+ }
47
+ },
48
+ text: {
49
+ enumerable: true,
50
+ value: async function () {
51
+ (0, _utils.brandCheck)(this, res?.constructor);
52
+ const blob = await this.blob();
53
+ return blob.text();
54
+ }
55
+ }
56
+ });
57
+ }
58
+ return Object.defineProperties(res, {
59
+ body: {
60
+ enumerable: true,
61
+ value: async function () {
62
+ (0, _utils.brandCheck)(this, res?.constructor);
63
+ if (this.bodyUsed) {
64
+ throw new TypeError('Response stream already read');
65
+ }
66
+ let body = [];
67
+ for await (const chunk of (0, _utils.decompress)(this, this.headers[HTTP2_HEADER_CONTENT_ENCODING])) {
68
+ body.push(chunk);
69
+ }
70
+ body = Buffer.concat(body);
71
+ if (!body.length && parse) {
72
+ return null;
73
+ }
74
+ if (body.length && parse) {
75
+ const contentType = this.headers[HTTP2_HEADER_CONTENT_TYPE] ?? '';
76
+ const charset = contentType.split(';').find(it => /charset=/i.test(it))?.toLowerCase().replace('charset=', '').replace('iso-8859-1', 'latin1').trim() || 'utf-8';
77
+ if (/\bjson\b/i.test(contentType)) {
78
+ body = JSON.parse(body.toString(charset));
79
+ } else if (/\b(?:text|xml)\b/i.test(contentType)) {
80
+ if (/\b(?:latin1|ucs-2|utf-(?:8|16le))\b/i.test(charset)) {
81
+ body = body.toString(charset);
82
+ } else {
83
+ body = new TextDecoder(charset).decode(body);
84
+ }
85
+ }
86
+ }
87
+ return body;
88
+ },
89
+ writable: true
90
+ },
91
+ bodyUsed: {
92
+ enumerable: true,
93
+ get() {
94
+ return this.readableEnded;
95
+ }
96
+ }
97
+ });
98
+ };
99
+ exports.mixin = mixin;
@@ -8,6 +8,7 @@ var _constants = require("./constants");
8
8
  var _cookies = require("./cookies");
9
9
  var _errors = require("./errors");
10
10
  var _index = _interopRequireDefault(require("./index"));
11
+ var _mixin = require("./mixin");
11
12
  var _utils = require("./utils");
12
13
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
14
  const {
@@ -74,7 +75,7 @@ const postflight = (req, res, options, {
74
75
  if (!(0, _utils.sameOrigin)(location, url)) {
75
76
  Reflect.set(options, 'h2', false);
76
77
  if ([_constants.requestCredentials.omit, _constants.requestCredentials.sameOrigin].includes(credentials)) {
77
- Reflect.deleteProperty(options.headers, HTTP2_HEADER_AUTHORIZATION);
78
+ Object.keys(options.headers).filter(it => new RegExp(HTTP2_HEADER_AUTHORIZATION, 'i').test(it)).forEach(it => Reflect.deleteProperty(options.headers, it));
78
79
  location.password = location.username = '';
79
80
  if (credentials === _constants.requestCredentials.omit) {
80
81
  options.cookies = false;
@@ -97,7 +98,7 @@ const postflight = (req, res, options, {
97
98
  interval = Number(interval) * 1000 || new Date(interval) - Date.now();
98
99
  if (interval > options.maxRetryAfter) {
99
100
  return res.emit('error', (0, _utils.maxRetryAfterError)(interval, {
100
- cause: (0, _utils.mixin)(res, options)
101
+ cause: (0, _mixin.mixin)(res, options)
101
102
  }));
102
103
  }
103
104
  return (0, _promises.setTimeout)(interval).then(() => (0, _index.default)(options.url, options).then(resolve, reject));
@@ -106,8 +107,8 @@ const postflight = (req, res, options, {
106
107
  }
107
108
  }
108
109
  if (statusCode >= HTTP_STATUS_BAD_REQUEST) {
109
- return reject((0, _utils.mixin)(res, options));
110
+ return reject((0, _mixin.mixin)(res, options));
110
111
  }
111
- resolve((0, _utils.mixin)(res, options));
112
+ resolve((0, _mixin.mixin)(res, options));
112
113
  };
113
114
  exports.postflight = postflight;
package/dist/utils.js CHANGED
@@ -1,10 +1,9 @@
1
1
  "use strict";
2
2
 
3
3
  exports.__esModule = true;
4
- exports.sanitize = exports.sameOrigin = exports.mixin = exports.merge = exports.maxRetryAfterError = exports.maxRetryAfter = exports.dispatch = exports.decompress = exports.compress = exports.brandCheck = exports.affix = exports.admix = void 0;
4
+ exports.sameOrigin = exports.normalize = exports.merge = exports.maxRetryAfterError = exports.maxRetryAfter = exports.dispatch = exports.decompress = exports.compress = exports.brandCheck = exports.affix = exports.admix = void 0;
5
5
  exports.tap = tap;
6
- exports.validation = exports.unwind = exports.transform = exports.transfer = void 0;
7
- var _nodeBuffer = require("node:buffer");
6
+ exports.unwind = exports.transform = exports.transfer = void 0;
8
7
  var _nodeHttp = _interopRequireDefault(require("node:http"));
9
8
  var _nodeHttp2 = _interopRequireDefault(require("node:http2"));
10
9
  var _nodeHttps = _interopRequireDefault(require("node:https"));
@@ -14,7 +13,6 @@ var _promises = require("node:timers/promises");
14
13
  var _nodeUtil = require("node:util");
15
14
  var _nodeZlib = _interopRequireDefault(require("node:zlib"));
16
15
  var _ackn = require("./ackn");
17
- var _constants = require("./constants");
18
16
  var _errors = require("./errors");
19
17
  var _file = require("./file");
20
18
  var _formdata = require("./formdata");
@@ -28,9 +26,7 @@ const {
28
26
  HTTP2_HEADER_CONTENT_LENGTH,
29
27
  HTTP2_HEADER_CONTENT_TYPE,
30
28
  HTTP2_HEADER_RETRY_AFTER,
31
- HTTP2_HEADER_STATUS,
32
- HTTP2_METHOD_GET,
33
- HTTP2_METHOD_HEAD
29
+ HTTP2_HEADER_STATUS
34
30
  } = _nodeHttp2.default.constants;
35
31
  const admix = (res, headers, options) => {
36
32
  const {
@@ -151,103 +147,16 @@ const merge = (target = {}, ...rest) => {
151
147
  return target;
152
148
  };
153
149
  exports.merge = merge;
154
- const mixin = (res, {
155
- digest = false,
156
- parse = false
157
- } = {}) => {
158
- if (!digest) {
159
- Object.defineProperties(res, {
160
- arrayBuffer: {
161
- enumerable: true,
162
- value: async function () {
163
- brandCheck(this, res?.constructor);
164
- parse &&= false;
165
- const {
166
- buffer,
167
- byteLength,
168
- byteOffset
169
- } = await this.body();
170
- return buffer.slice(byteOffset, byteOffset + byteLength);
171
- }
172
- },
173
- blob: {
174
- enumerable: true,
175
- value: async function () {
176
- brandCheck(this, res?.constructor);
177
- const val = await this.arrayBuffer();
178
- return new _nodeBuffer.Blob([val]);
179
- }
180
- },
181
- json: {
182
- enumerable: true,
183
- value: async function () {
184
- brandCheck(this, res?.constructor);
185
- const val = await this.text();
186
- return JSON.parse(val);
187
- }
188
- },
189
- text: {
190
- enumerable: true,
191
- value: async function () {
192
- brandCheck(this, res?.constructor);
193
- const blob = await this.blob();
194
- return blob.text();
195
- }
196
- }
197
- });
198
- }
199
- return Object.defineProperties(res, {
200
- body: {
201
- enumerable: true,
202
- value: async function () {
203
- brandCheck(this, res?.constructor);
204
- if (this.bodyUsed) {
205
- throw new TypeError('Response stream already read');
206
- }
207
- let body = [];
208
- for await (const chunk of decompress(this, this.headers[HTTP2_HEADER_CONTENT_ENCODING])) {
209
- body.push(chunk);
210
- }
211
- body = Buffer.concat(body);
212
- if (!body.length && parse) {
213
- return null;
214
- }
215
- if (body.length && parse) {
216
- const contentType = this.headers[HTTP2_HEADER_CONTENT_TYPE] ?? '';
217
- const charset = contentType.split(';').find(it => /charset=/i.test(it))?.toLowerCase().replace('charset=', '').replace('iso-8859-1', 'latin1').trim() || 'utf-8';
218
- if (/\bjson\b/i.test(contentType)) {
219
- body = JSON.parse(body.toString(charset));
220
- } else if (/\b(?:text|xml)\b/i.test(contentType)) {
221
- if (/\b(?:latin1|ucs-2|utf-(?:8|16le))\b/i.test(charset)) {
222
- body = body.toString(charset);
223
- } else {
224
- body = new TextDecoder(charset).decode(body);
225
- }
226
- }
227
- }
228
- return body;
229
- },
230
- writable: true
231
- },
232
- bodyUsed: {
233
- enumerable: true,
234
- get() {
235
- return this.readableEnded;
236
- }
237
- }
238
- });
239
- };
240
- exports.mixin = mixin;
241
- const sanitize = (url, options = {}) => {
150
+ const normalize = (url, options = {}) => {
242
151
  if (options.trimTrailingSlashes) {
243
152
  url = `${url}`.replace(/(?<!:)\/+/g, '/');
244
153
  }
245
- url = new URL(url);
154
+ url = new URL(url, options.baseURL);
246
155
  return Object.assign(options, {
247
156
  url
248
157
  });
249
158
  };
250
- exports.sanitize = sanitize;
159
+ exports.normalize = normalize;
251
160
  const sameOrigin = (a, b) => a.protocol === b.protocol && a.hostname === b.hostname && a.port === b.port;
252
161
  exports.sameOrigin = sameOrigin;
253
162
  async function* tap(value) {
@@ -407,17 +316,4 @@ const transform = async options => {
407
316
  };
408
317
  exports.transform = transform;
409
318
  const unwind = encodings => encodings.split(',').map(it => it.trim());
410
- exports.unwind = unwind;
411
- const validation = (options = {}) => {
412
- if (options.body && [HTTP2_METHOD_GET, HTTP2_METHOD_HEAD].includes(options.method)) {
413
- throw new TypeError(`Request with ${HTTP2_METHOD_GET}/${HTTP2_METHOD_HEAD} method cannot have body.`);
414
- }
415
- if (!Object.values(_constants.requestCredentials).includes(options.credentials)) {
416
- throw new TypeError(`Failed to read the 'credentials' property from 'options': The provided value '${options.credentials}' is not a valid enum value.`);
417
- }
418
- if (!Reflect.has(_constants.requestRedirect, options.redirect)) {
419
- throw new TypeError(`Failed to read the 'redirect' property from 'options': The provided value '${options.redirect}' is not a valid enum value.`);
420
- }
421
- return options;
422
- };
423
- exports.validation = validation;
319
+ exports.unwind = unwind;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.validation = void 0;
5
+ var _nodeHttp = _interopRequireDefault(require("node:http2"));
6
+ var _constants = require("./constants");
7
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
8
+ const {
9
+ HTTP2_METHOD_GET,
10
+ HTTP2_METHOD_HEAD
11
+ } = _nodeHttp.default.constants;
12
+ const validation = (options = {}) => {
13
+ if (options.body && [HTTP2_METHOD_GET, HTTP2_METHOD_HEAD].includes(options.method)) {
14
+ throw new TypeError(`Request with ${HTTP2_METHOD_GET}/${HTTP2_METHOD_HEAD} method cannot have body.`);
15
+ }
16
+ if (!Object.values(_constants.requestCredentials).includes(options.credentials)) {
17
+ throw new TypeError(`Failed to read the 'credentials' property from 'options': The provided value '${options.credentials}' is not a valid enum value.`);
18
+ }
19
+ if (!Reflect.has(_constants.requestRedirect, options.redirect)) {
20
+ throw new TypeError(`Failed to read the 'redirect' property from 'options': The provided value '${options.redirect}' is not a valid enum value.`);
21
+ }
22
+ return options;
23
+ };
24
+ exports.validation = validation;
package/package.json CHANGED
@@ -8,14 +8,14 @@
8
8
  "url": "https://github.com/bricss/rekwest/issues"
9
9
  },
10
10
  "devDependencies": {
11
- "@babel/cli": "^7.19.3",
12
- "@babel/core": "^7.20.5",
11
+ "@babel/cli": "^7.20.7",
12
+ "@babel/core": "^7.20.12",
13
13
  "@babel/eslint-parser": "^7.19.1",
14
14
  "@babel/preset-env": "^7.20.2",
15
15
  "c8": "^7.12.0",
16
- "eslint": "^8.28.0",
16
+ "eslint": "^8.33.0",
17
17
  "eslint-config-ultra-refined": "^2.10.0",
18
- "mocha": "^10.1.0"
18
+ "mocha": "^10.2.0"
19
19
  },
20
20
  "description": "The robust request library that humanity deserves 🌐",
21
21
  "engines": {
@@ -67,5 +67,5 @@
67
67
  "test:bail": "mocha --bail",
68
68
  "test:cover": "c8 --include=src --reporter=lcov --reporter=text npm test"
69
69
  },
70
- "version": "4.2.2"
70
+ "version": "4.3.0"
71
71
  }
package/src/formdata.mjs CHANGED
@@ -25,7 +25,7 @@ export class FormData {
25
25
  const prefix = `--${ boundary }${ CRLF }${ HTTP2_HEADER_CONTENT_DISPOSITION }: form-data`;
26
26
 
27
27
  const escape = (str) => str.replace(/\n/g, '%0A').replace(/\r/g, '%0D').replace(/"/g, '%22');
28
- const normalize = (value) => value.replace(/\r?\n|\r/g, CRLF);
28
+ const redress = (value) => value.replace(/\r?\n|\r/g, CRLF);
29
29
 
30
30
  return {
31
31
  contentType,
@@ -35,11 +35,11 @@ export class FormData {
35
35
  for (const [name, value] of fd) {
36
36
  if (value.constructor === String) {
37
37
  yield encoder.encode(`${ prefix }; name="${
38
- escape(normalize(name))
39
- }"${ CRLF.repeat(2) }${ normalize(value) }${ CRLF }`);
38
+ escape(redress(name))
39
+ }"${ CRLF.repeat(2) }${ redress(value) }${ CRLF }`);
40
40
  } else {
41
41
  yield encoder.encode(`${ prefix }; name="${
42
- escape(normalize(name))
42
+ escape(redress(name))
43
43
  }"${ value.name ? `; filename="${ escape(value.name) }"` : '' }${ CRLF }${
44
44
  HTTP2_HEADER_CONTENT_TYPE
45
45
  }: ${
package/src/index.mjs CHANGED
@@ -9,10 +9,10 @@ import {
9
9
  admix,
10
10
  affix,
11
11
  merge,
12
- sanitize,
12
+ normalize,
13
13
  transfer,
14
- validation,
15
14
  } from './utils.mjs';
15
+ import { validation } from './validation.mjs';
16
16
 
17
17
  export { constants } from 'node:http2';
18
18
 
@@ -23,14 +23,16 @@ export * from './errors.mjs';
23
23
  export * from './file.mjs';
24
24
  export * from './formdata.mjs';
25
25
  export * as mediatypes from './mediatypes.mjs';
26
+ export * from './mixin.mjs';
26
27
  export * from './utils.mjs';
28
+ export * from './validation.mjs';
27
29
 
28
30
  const {
29
31
  HTTP2_HEADER_CONTENT_TYPE,
30
32
  } = http2.constants;
31
33
 
32
34
  export default function rekwest(...args) {
33
- let options = sanitize(...args);
35
+ let options = normalize(...args);
34
36
 
35
37
  if (!options.redirected) {
36
38
  options = merge(rekwest.defaults, options);
@@ -45,7 +47,7 @@ Reflect.defineProperty(rekwest, 'stream', {
45
47
  const options = preflight({
46
48
  ...validation(merge(rekwest.defaults, {
47
49
  headers: { [HTTP2_HEADER_CONTENT_TYPE]: APPLICATION_OCTET_STREAM },
48
- }, sanitize(...args))),
50
+ }, normalize(...args))),
49
51
  redirect: requestRedirect.manual,
50
52
  });
51
53
 
package/src/mixin.mjs ADDED
@@ -0,0 +1,109 @@
1
+ import { Blob } from 'node:buffer';
2
+ import http2 from 'node:http2';
3
+ import {
4
+ brandCheck,
5
+ decompress,
6
+ } from './utils.mjs';
7
+
8
+ const {
9
+ HTTP2_HEADER_CONTENT_ENCODING,
10
+ HTTP2_HEADER_CONTENT_TYPE,
11
+ } = http2.constants;
12
+
13
+ export const mixin = (res, { digest = false, parse = false } = {}) => {
14
+ if (!digest) {
15
+ Object.defineProperties(res, {
16
+ arrayBuffer: {
17
+ enumerable: true,
18
+ value: async function () {
19
+ brandCheck(this, res?.constructor);
20
+ parse &&= false;
21
+ const { buffer, byteLength, byteOffset } = await this.body();
22
+
23
+ return buffer.slice(byteOffset, byteOffset + byteLength);
24
+ },
25
+ },
26
+ blob: {
27
+ enumerable: true,
28
+ value: async function () {
29
+ brandCheck(this, res?.constructor);
30
+ const val = await this.arrayBuffer();
31
+
32
+ return new Blob([val]);
33
+ },
34
+ },
35
+ json: {
36
+ enumerable: true,
37
+ value: async function () {
38
+ brandCheck(this, res?.constructor);
39
+ const val = await this.text();
40
+
41
+ return JSON.parse(val);
42
+ },
43
+ },
44
+ text: {
45
+ enumerable: true,
46
+ value: async function () {
47
+ brandCheck(this, res?.constructor);
48
+ const blob = await this.blob();
49
+
50
+ return blob.text();
51
+ },
52
+ },
53
+ });
54
+ }
55
+
56
+ return Object.defineProperties(res, {
57
+ body: {
58
+ enumerable: true,
59
+ value: async function () {
60
+ brandCheck(this, res?.constructor);
61
+
62
+ if (this.bodyUsed) {
63
+ throw new TypeError('Response stream already read');
64
+ }
65
+
66
+ let body = [];
67
+
68
+ for await (const chunk of decompress(this, this.headers[HTTP2_HEADER_CONTENT_ENCODING])) {
69
+ body.push(chunk);
70
+ }
71
+
72
+ body = Buffer.concat(body);
73
+
74
+ if (!body.length && parse) {
75
+ return null;
76
+ }
77
+
78
+ if (body.length && parse) {
79
+ const contentType = this.headers[HTTP2_HEADER_CONTENT_TYPE] ?? '';
80
+ const charset = contentType.split(';')
81
+ .find((it) => /charset=/i.test(it))
82
+ ?.toLowerCase()
83
+ .replace('charset=', '')
84
+ .replace('iso-8859-1', 'latin1')
85
+ .trim() || 'utf-8';
86
+
87
+ if (/\bjson\b/i.test(contentType)) {
88
+ body = JSON.parse(body.toString(charset));
89
+ } else if (/\b(?:text|xml)\b/i.test(contentType)) {
90
+ if (/\b(?:latin1|ucs-2|utf-(?:8|16le))\b/i.test(charset)) {
91
+ body = body.toString(charset);
92
+ } else {
93
+ body = new TextDecoder(charset).decode(body);
94
+ }
95
+ }
96
+ }
97
+
98
+ return body;
99
+ },
100
+ writable: true,
101
+ },
102
+ bodyUsed: {
103
+ enumerable: true,
104
+ get() {
105
+ return this.readableEnded;
106
+ },
107
+ },
108
+ });
109
+ };
@@ -8,10 +8,10 @@ import {
8
8
  import { Cookies } from './cookies.mjs';
9
9
  import { RequestError } from './errors.mjs';
10
10
  import rekwest from './index.mjs';
11
+ import { mixin } from './mixin.mjs';
11
12
  import {
12
13
  admix,
13
14
  maxRetryAfterError,
14
- mixin,
15
15
  sameOrigin,
16
16
  } from './utils.mjs';
17
17
 
@@ -83,7 +83,8 @@ export const postflight = (req, res, options, { reject, resolve }) => {
83
83
  requestCredentials.omit,
84
84
  requestCredentials.sameOrigin,
85
85
  ].includes(credentials)) {
86
- Reflect.deleteProperty(options.headers, HTTP2_HEADER_AUTHORIZATION);
86
+ Object.keys(options.headers).filter((it) => new RegExp(HTTP2_HEADER_AUTHORIZATION, 'i').test(it))
87
+ .forEach((it) => Reflect.deleteProperty(options.headers, it));
87
88
  location.password = location.username = '';
88
89
  if (credentials === requestCredentials.omit) {
89
90
  options.cookies = false;
package/src/utils.mjs CHANGED
@@ -1,4 +1,3 @@
1
- import { Blob } from 'node:buffer';
2
1
  import http from 'node:http';
3
2
  import http2 from 'node:http2';
4
3
  import https from 'node:https';
@@ -11,10 +10,6 @@ import { setTimeout as setTimeoutPromise } from 'node:timers/promises';
11
10
  import { types } from 'node:util';
12
11
  import zlib from 'node:zlib';
13
12
  import { ackn } from './ackn.mjs';
14
- import {
15
- requestCredentials,
16
- requestRedirect,
17
- } from './constants.mjs';
18
13
  import {
19
14
  RequestError,
20
15
  TimeoutError,
@@ -36,8 +31,6 @@ const {
36
31
  HTTP2_HEADER_CONTENT_TYPE,
37
32
  HTTP2_HEADER_RETRY_AFTER,
38
33
  HTTP2_HEADER_STATUS,
39
- HTTP2_METHOD_GET,
40
- HTTP2_METHOD_HEAD,
41
34
  } = http2.constants;
42
35
 
43
36
  export const admix = (res, headers, options) => {
@@ -178,110 +171,12 @@ export const merge = (target = {}, ...rest) => {
178
171
  return target;
179
172
  };
180
173
 
181
- export const mixin = (res, { digest = false, parse = false } = {}) => {
182
- if (!digest) {
183
- Object.defineProperties(res, {
184
- arrayBuffer: {
185
- enumerable: true,
186
- value: async function () {
187
- brandCheck(this, res?.constructor);
188
- parse &&= false;
189
- const { buffer, byteLength, byteOffset } = await this.body();
190
-
191
- return buffer.slice(byteOffset, byteOffset + byteLength);
192
- },
193
- },
194
- blob: {
195
- enumerable: true,
196
- value: async function () {
197
- brandCheck(this, res?.constructor);
198
- const val = await this.arrayBuffer();
199
-
200
- return new Blob([val]);
201
- },
202
- },
203
- json: {
204
- enumerable: true,
205
- value: async function () {
206
- brandCheck(this, res?.constructor);
207
- const val = await this.text();
208
-
209
- return JSON.parse(val);
210
- },
211
- },
212
- text: {
213
- enumerable: true,
214
- value: async function () {
215
- brandCheck(this, res?.constructor);
216
- const blob = await this.blob();
217
-
218
- return blob.text();
219
- },
220
- },
221
- });
222
- }
223
-
224
- return Object.defineProperties(res, {
225
- body: {
226
- enumerable: true,
227
- value: async function () {
228
- brandCheck(this, res?.constructor);
229
-
230
- if (this.bodyUsed) {
231
- throw new TypeError('Response stream already read');
232
- }
233
-
234
- let body = [];
235
-
236
- for await (const chunk of decompress(this, this.headers[HTTP2_HEADER_CONTENT_ENCODING])) {
237
- body.push(chunk);
238
- }
239
-
240
- body = Buffer.concat(body);
241
-
242
- if (!body.length && parse) {
243
- return null;
244
- }
245
-
246
- if (body.length && parse) {
247
- const contentType = this.headers[HTTP2_HEADER_CONTENT_TYPE] ?? '';
248
- const charset = contentType.split(';')
249
- .find((it) => /charset=/i.test(it))
250
- ?.toLowerCase()
251
- .replace('charset=', '')
252
- .replace('iso-8859-1', 'latin1')
253
- .trim() || 'utf-8';
254
-
255
- if (/\bjson\b/i.test(contentType)) {
256
- body = JSON.parse(body.toString(charset));
257
- } else if (/\b(?:text|xml)\b/i.test(contentType)) {
258
- if (/\b(?:latin1|ucs-2|utf-(?:8|16le))\b/i.test(charset)) {
259
- body = body.toString(charset);
260
- } else {
261
- body = new TextDecoder(charset).decode(body);
262
- }
263
- }
264
- }
265
-
266
- return body;
267
- },
268
- writable: true,
269
- },
270
- bodyUsed: {
271
- enumerable: true,
272
- get() {
273
- return this.readableEnded;
274
- },
275
- },
276
- });
277
- };
278
-
279
- export const sanitize = (url, options = {}) => {
174
+ export const normalize = (url, options = {}) => {
280
175
  if (options.trimTrailingSlashes) {
281
176
  url = `${ url }`.replace(/(?<!:)\/+/g, '/');
282
177
  }
283
178
 
284
- url = new URL(url);
179
+ url = new URL(url, options.baseURL);
285
180
 
286
181
  return Object.assign(options, { url });
287
182
  };
@@ -452,26 +347,3 @@ export const transform = async (options) => {
452
347
  };
453
348
 
454
349
  export const unwind = (encodings) => encodings.split(',').map((it) => it.trim());
455
-
456
- export const validation = (options = {}) => {
457
- if (options.body && [
458
- HTTP2_METHOD_GET,
459
- HTTP2_METHOD_HEAD,
460
- ].includes(options.method)) {
461
- throw new TypeError(`Request with ${ HTTP2_METHOD_GET }/${ HTTP2_METHOD_HEAD } method cannot have body.`);
462
- }
463
-
464
- if (!Object.values(requestCredentials).includes(options.credentials)) {
465
- throw new TypeError(`Failed to read the 'credentials' property from 'options': The provided value '${
466
- options.credentials
467
- }' is not a valid enum value.`);
468
- }
469
-
470
- if (!Reflect.has(requestRedirect, options.redirect)) {
471
- throw new TypeError(`Failed to read the 'redirect' property from 'options': The provided value '${
472
- options.redirect
473
- }' is not a valid enum value.`);
474
- }
475
-
476
- return options;
477
- };
@@ -0,0 +1,33 @@
1
+ import http2 from 'node:http2';
2
+ import {
3
+ requestCredentials,
4
+ requestRedirect,
5
+ } from './constants.mjs';
6
+
7
+ const {
8
+ HTTP2_METHOD_GET,
9
+ HTTP2_METHOD_HEAD,
10
+ } = http2.constants;
11
+
12
+ export const validation = (options = {}) => {
13
+ if (options.body && [
14
+ HTTP2_METHOD_GET,
15
+ HTTP2_METHOD_HEAD,
16
+ ].includes(options.method)) {
17
+ throw new TypeError(`Request with ${ HTTP2_METHOD_GET }/${ HTTP2_METHOD_HEAD } method cannot have body.`);
18
+ }
19
+
20
+ if (!Object.values(requestCredentials).includes(options.credentials)) {
21
+ throw new TypeError(`Failed to read the 'credentials' property from 'options': The provided value '${
22
+ options.credentials
23
+ }' is not a valid enum value.`);
24
+ }
25
+
26
+ if (!Reflect.has(requestRedirect, options.redirect)) {
27
+ throw new TypeError(`Failed to read the 'redirect' property from 'options': The provided value '${
28
+ options.redirect
29
+ }' is not a valid enum value.`);
30
+ }
31
+
32
+ return options;
33
+ };