rekwest 2.2.0 → 2.3.3
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 +1 -1
- package/dist/formdata.js +17 -10
- package/dist/helpers.js +8 -9
- package/package.json +13 -9
- package/src/formdata.mjs +24 -18
- package/src/helpers.mjs +10 -12
package/README.md
CHANGED
|
@@ -85,7 +85,7 @@ const file = new File(['bits'], 'file.dab');
|
|
|
85
85
|
const readable = Readable.from('bits');
|
|
86
86
|
|
|
87
87
|
const fd = new FormData({
|
|
88
|
-
aux: Date.now(), //
|
|
88
|
+
aux: Date.now(), // either [[key, value]], or kv sequenceable
|
|
89
89
|
});
|
|
90
90
|
|
|
91
91
|
fd.append('celestial', 'payload');
|
package/dist/formdata.js
CHANGED
|
@@ -17,6 +17,7 @@ var _mediatypes = require("./mediatypes.mjs");
|
|
|
17
17
|
|
|
18
18
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
19
19
|
|
|
20
|
+
const CRLF = '\r\n';
|
|
20
21
|
const {
|
|
21
22
|
HTTP2_HEADER_CONTENT_DISPOSITION,
|
|
22
23
|
HTTP2_HEADER_CONTENT_TYPE
|
|
@@ -26,11 +27,11 @@ class FormData {
|
|
|
26
27
|
static actuate(fd) {
|
|
27
28
|
const boundary = (0, _crypto.randomBytes)(24).toString('hex');
|
|
28
29
|
const contentType = `${_mediatypes.MULTIPART_FORM_DATA}; boundary=${boundary}`;
|
|
29
|
-
const prefix = `--${boundary}
|
|
30
|
+
const prefix = `--${boundary}${CRLF}${HTTP2_HEADER_CONTENT_DISPOSITION}: form-data`;
|
|
30
31
|
|
|
31
32
|
const escape = str => str.replace(/\n/g, '%0A').replace(/\r/g, '%0D').replace(/"/g, '%22');
|
|
32
33
|
|
|
33
|
-
const normalize = value => value.replace(/\r?\n|\r/g,
|
|
34
|
+
const normalize = value => value.replace(/\r?\n|\r/g, CRLF);
|
|
34
35
|
|
|
35
36
|
return {
|
|
36
37
|
contentType,
|
|
@@ -40,11 +41,11 @@ class FormData {
|
|
|
40
41
|
|
|
41
42
|
for (const [name, value] of fd) {
|
|
42
43
|
if (value.constructor === String) {
|
|
43
|
-
yield encoder.encode(`${prefix}; name="${escape(normalize(name))}"
|
|
44
|
+
yield encoder.encode(`${prefix}; name="${escape(normalize(name))}"${CRLF.repeat(2)}${normalize(value)}${CRLF}`);
|
|
44
45
|
} else {
|
|
45
|
-
yield encoder.encode(`${prefix}; name="${escape(normalize(name))}"${value.name ? `; filename="${escape(value.name)}"` : ''}
|
|
46
|
+
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)}`);
|
|
46
47
|
yield* (0, _helpers.tap)(value);
|
|
47
|
-
yield encoder.encode(
|
|
48
|
+
yield encoder.encode(CRLF);
|
|
48
49
|
}
|
|
49
50
|
}
|
|
50
51
|
|
|
@@ -87,11 +88,17 @@ class FormData {
|
|
|
87
88
|
}
|
|
88
89
|
|
|
89
90
|
constructor(input) {
|
|
90
|
-
if (input
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
91
|
+
if (input === Object(input) && (input?.constructor === Object || Reflect.has(input, Symbol.iterator))) {
|
|
92
|
+
if (input.constructor !== Object) {
|
|
93
|
+
input = Array.from(input);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (Array.isArray(input)) {
|
|
97
|
+
if (!input.every(it => Array.isArray(it))) {
|
|
98
|
+
throw new TypeError(`Failed to construct '${this[Symbol.toStringTag]}': The provided value cannot be converted to a sequence.`);
|
|
99
|
+
} else if (!input.every(it => it.length === 2)) {
|
|
100
|
+
throw new TypeError(`Failed to construct '${this[Symbol.toStringTag]}': Sequence initializer must only contain pair elements.`);
|
|
101
|
+
}
|
|
95
102
|
}
|
|
96
103
|
|
|
97
104
|
if (input.constructor === Object) {
|
package/dist/helpers.js
CHANGED
|
@@ -51,7 +51,7 @@ const inflate = (0, _util.promisify)(_zlib.default.inflate);
|
|
|
51
51
|
const compress = (buf, encoding, {
|
|
52
52
|
async = false
|
|
53
53
|
} = {}) => {
|
|
54
|
-
encoding &&= encoding.match(
|
|
54
|
+
encoding &&= encoding.match(/(?<encoding>\bbr\b|\bdeflate\b|\bgzip\b)/i)?.groups.encoding.toLowerCase();
|
|
55
55
|
const compressor = {
|
|
56
56
|
br: async ? brotliCompress : _zlib.default.brotliCompressSync,
|
|
57
57
|
deflate: async ? deflate : _zlib.default.deflateSync,
|
|
@@ -65,7 +65,7 @@ exports.compress = compress;
|
|
|
65
65
|
const decompress = (buf, encoding, {
|
|
66
66
|
async = false
|
|
67
67
|
} = {}) => {
|
|
68
|
-
encoding &&= encoding.match(
|
|
68
|
+
encoding &&= encoding.match(/(?<encoding>\bbr\b|\bdeflate\b|\bgzip\b)/i)?.groups.encoding.toLowerCase();
|
|
69
69
|
const decompressor = {
|
|
70
70
|
br: async ? brotliDecompress : _zlib.default.brotliDecompressSync,
|
|
71
71
|
deflate: async ? inflate : _zlib.default.inflateSync,
|
|
@@ -200,13 +200,12 @@ const premix = (res, {
|
|
|
200
200
|
arrayBuffer: {
|
|
201
201
|
enumerable: true,
|
|
202
202
|
value: async function () {
|
|
203
|
-
|
|
204
|
-
parse = false;
|
|
203
|
+
parse &&= false;
|
|
205
204
|
const {
|
|
206
205
|
buffer,
|
|
207
206
|
byteLength,
|
|
208
207
|
byteOffset
|
|
209
|
-
} = await this.body()
|
|
208
|
+
} = await this.body();
|
|
210
209
|
return buffer.slice(byteOffset, byteOffset + byteLength);
|
|
211
210
|
}
|
|
212
211
|
},
|
|
@@ -258,12 +257,12 @@ const premix = (res, {
|
|
|
258
257
|
|
|
259
258
|
if (spool.length && parse) {
|
|
260
259
|
const contentType = this.headers[HTTP2_HEADER_CONTENT_TYPE] ?? '';
|
|
261
|
-
const charset = contentType.split(';').find(it => /charset=/i.test(it))?.toLowerCase()
|
|
260
|
+
const charset = contentType.split(';').find(it => /charset=/i.test(it))?.toLowerCase().replace('charset=', '').replace('iso-8859-1', 'latin1').trim() || 'utf-8';
|
|
262
261
|
|
|
263
|
-
if (/
|
|
262
|
+
if (/\bjson\b/i.test(contentType)) {
|
|
264
263
|
spool = JSON.parse(spool.toString(charset));
|
|
265
|
-
} else if (
|
|
266
|
-
if (
|
|
264
|
+
} else if (/\b(text|xml)\b/i.test(contentType)) {
|
|
265
|
+
if (/\b(latin1|ucs-2|utf-(8|16le))\b/.test(charset)) {
|
|
267
266
|
spool = spool.toString(charset);
|
|
268
267
|
} else {
|
|
269
268
|
spool = new TextDecoder(charset).decode(spool);
|
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.16.
|
|
12
|
-
"@babel/core": "^7.16.
|
|
13
|
-
"@babel/eslint-parser": "^7.16.
|
|
14
|
-
"@babel/preset-env": "^7.16.
|
|
15
|
-
"c8": "^7.
|
|
16
|
-
"eslint": "^8.
|
|
17
|
-
"eslint-config-ultra-refined": "^2.
|
|
18
|
-
"mocha": "^9.
|
|
11
|
+
"@babel/cli": "^7.16.8",
|
|
12
|
+
"@babel/core": "^7.16.12",
|
|
13
|
+
"@babel/eslint-parser": "^7.16.5",
|
|
14
|
+
"@babel/preset-env": "^7.16.11",
|
|
15
|
+
"c8": "^7.11.0",
|
|
16
|
+
"eslint": "^8.7.0",
|
|
17
|
+
"eslint-config-ultra-refined": "^2.3.0",
|
|
18
|
+
"mocha": "^9.2.0"
|
|
19
19
|
},
|
|
20
20
|
"description": "The robust request library that humanity deserves 🌐",
|
|
21
21
|
"engines": {
|
|
@@ -33,9 +33,13 @@
|
|
|
33
33
|
"keywords": [
|
|
34
34
|
"fetch",
|
|
35
35
|
"fetch-alike",
|
|
36
|
+
"formdata",
|
|
36
37
|
"http",
|
|
37
38
|
"https",
|
|
39
|
+
"h2",
|
|
40
|
+
"h2c",
|
|
38
41
|
"http2",
|
|
42
|
+
"multipart",
|
|
39
43
|
"request"
|
|
40
44
|
],
|
|
41
45
|
"license": "MIT",
|
|
@@ -55,5 +59,5 @@
|
|
|
55
59
|
"test": "mocha --exit --recursive",
|
|
56
60
|
"test:cover": "c8 --include=src --reporter=lcov --reporter=text npm test"
|
|
57
61
|
},
|
|
58
|
-
"version": "2.
|
|
62
|
+
"version": "2.3.3"
|
|
59
63
|
}
|
package/src/formdata.mjs
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
MULTIPART_FORM_DATA,
|
|
9
9
|
} from './mediatypes.mjs';
|
|
10
10
|
|
|
11
|
+
const CRLF = '\r\n';
|
|
11
12
|
const {
|
|
12
13
|
HTTP2_HEADER_CONTENT_DISPOSITION,
|
|
13
14
|
HTTP2_HEADER_CONTENT_TYPE,
|
|
@@ -18,10 +19,10 @@ export class FormData {
|
|
|
18
19
|
static actuate(fd) {
|
|
19
20
|
const boundary = randomBytes(24).toString('hex');
|
|
20
21
|
const contentType = `${ MULTIPART_FORM_DATA }; boundary=${ boundary }`;
|
|
21
|
-
const prefix = `--${ boundary }
|
|
22
|
+
const prefix = `--${ boundary }${ CRLF }${ HTTP2_HEADER_CONTENT_DISPOSITION }: form-data`;
|
|
22
23
|
|
|
23
24
|
const escape = (str) => str.replace(/\n/g, '%0A').replace(/\r/g, '%0D').replace(/"/g, '%22');
|
|
24
|
-
const normalize = (value) => value.replace(/\r?\n|\r/g,
|
|
25
|
+
const normalize = (value) => value.replace(/\r?\n|\r/g, CRLF);
|
|
25
26
|
|
|
26
27
|
return {
|
|
27
28
|
contentType,
|
|
@@ -32,17 +33,17 @@ export class FormData {
|
|
|
32
33
|
if (value.constructor === String) {
|
|
33
34
|
yield encoder.encode(`${ prefix }; name="${
|
|
34
35
|
escape(normalize(name))
|
|
35
|
-
}"
|
|
36
|
+
}"${ CRLF.repeat(2) }${ normalize(value) }${ CRLF }`);
|
|
36
37
|
} else {
|
|
37
38
|
yield encoder.encode(`${ prefix }; name="${
|
|
38
39
|
escape(normalize(name))
|
|
39
|
-
}"${ value.name ? `; filename="${ escape(value.name) }"` : '' }
|
|
40
|
+
}"${ value.name ? `; filename="${ escape(value.name) }"` : '' }${ CRLF }${
|
|
40
41
|
HTTP2_HEADER_CONTENT_TYPE
|
|
41
42
|
}: ${
|
|
42
43
|
value.type || APPLICATION_OCTET_STREAM
|
|
43
|
-
}
|
|
44
|
+
}${ CRLF.repeat(2) }`);
|
|
44
45
|
yield* tap(value);
|
|
45
|
-
yield encoder.encode(
|
|
46
|
+
yield encoder.encode(CRLF);
|
|
46
47
|
}
|
|
47
48
|
}
|
|
48
49
|
|
|
@@ -84,18 +85,23 @@ export class FormData {
|
|
|
84
85
|
}
|
|
85
86
|
|
|
86
87
|
constructor(input) {
|
|
87
|
-
if (input
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
88
|
+
if (input === Object(input)
|
|
89
|
+
&& (input?.constructor === Object || Reflect.has(input, Symbol.iterator))) {
|
|
90
|
+
|
|
91
|
+
if (input.constructor !== Object) {
|
|
92
|
+
input = Array.from(input);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (Array.isArray(input)) {
|
|
96
|
+
if (!input.every((it) => Array.isArray(it))) {
|
|
97
|
+
throw new TypeError(`Failed to construct '${
|
|
98
|
+
this[Symbol.toStringTag]
|
|
99
|
+
}': The provided value cannot be converted to a sequence.`);
|
|
100
|
+
} else if (!input.every((it) => it.length === 2)) {
|
|
101
|
+
throw new TypeError(`Failed to construct '${
|
|
102
|
+
this[Symbol.toStringTag]
|
|
103
|
+
}': Sequence initializer must only contain pair elements.`);
|
|
104
|
+
}
|
|
99
105
|
}
|
|
100
106
|
|
|
101
107
|
if (input.constructor === Object) {
|
package/src/helpers.mjs
CHANGED
|
@@ -44,7 +44,7 @@ const deflate = promisify(zlib.deflate);
|
|
|
44
44
|
const inflate = promisify(zlib.inflate);
|
|
45
45
|
|
|
46
46
|
export const compress = (buf, encoding, { async = false } = {}) => {
|
|
47
|
-
encoding &&= encoding.match(
|
|
47
|
+
encoding &&= encoding.match(/(?<encoding>\bbr\b|\bdeflate\b|\bgzip\b)/i)?.groups.encoding.toLowerCase();
|
|
48
48
|
const compressor = {
|
|
49
49
|
br: async ? brotliCompress : zlib.brotliCompressSync,
|
|
50
50
|
deflate: async ? deflate : zlib.deflateSync,
|
|
@@ -55,7 +55,7 @@ export const compress = (buf, encoding, { async = false } = {}) => {
|
|
|
55
55
|
};
|
|
56
56
|
|
|
57
57
|
export const decompress = (buf, encoding, { async = false } = {}) => {
|
|
58
|
-
encoding &&= encoding.match(
|
|
58
|
+
encoding &&= encoding.match(/(?<encoding>\bbr\b|\bdeflate\b|\bgzip\b)/i)?.groups.encoding.toLowerCase();
|
|
59
59
|
const decompressor = {
|
|
60
60
|
br: async ? brotliDecompress : zlib.brotliDecompressSync,
|
|
61
61
|
deflate: async ? inflate : zlib.inflateSync,
|
|
@@ -183,10 +183,8 @@ export const premix = (res, { digest = false, parse = false } = {}) => {
|
|
|
183
183
|
arrayBuffer: {
|
|
184
184
|
enumerable: true,
|
|
185
185
|
value: async function () {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
parse = false;
|
|
189
|
-
const { buffer, byteLength, byteOffset } = await this.body().finally(() => parse = stash);
|
|
186
|
+
parse &&= false;
|
|
187
|
+
const { buffer, byteLength, byteOffset } = await this.body();
|
|
190
188
|
|
|
191
189
|
return buffer.slice(byteOffset, byteOffset + byteLength);
|
|
192
190
|
},
|
|
@@ -243,14 +241,14 @@ export const premix = (res, { digest = false, parse = false } = {}) => {
|
|
|
243
241
|
const charset = contentType.split(';')
|
|
244
242
|
.find((it) => /charset=/i.test(it))
|
|
245
243
|
?.toLowerCase()
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
244
|
+
.replace('charset=', '')
|
|
245
|
+
.replace('iso-8859-1', 'latin1')
|
|
246
|
+
.trim() || 'utf-8';
|
|
249
247
|
|
|
250
|
-
if (/
|
|
248
|
+
if (/\bjson\b/i.test(contentType)) {
|
|
251
249
|
spool = JSON.parse(spool.toString(charset));
|
|
252
|
-
} else if (
|
|
253
|
-
if (
|
|
250
|
+
} else if (/\b(text|xml)\b/i.test(contentType)) {
|
|
251
|
+
if (/\b(latin1|ucs-2|utf-(8|16le))\b/.test(charset)) {
|
|
254
252
|
spool = spool.toString(charset);
|
|
255
253
|
} else {
|
|
256
254
|
spool = new TextDecoder(charset).decode(spool);
|