@gjsify/fetch 0.0.4 → 0.1.1
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 +27 -2
- package/globals.mjs +12 -0
- package/lib/body.d.ts +69 -0
- package/lib/body.js +375 -0
- package/lib/errors/abort-error.d.ts +7 -0
- package/lib/errors/abort-error.js +9 -0
- package/lib/errors/base.d.ts +6 -0
- package/lib/errors/base.js +17 -0
- package/lib/errors/fetch-error.d.ts +16 -0
- package/lib/errors/fetch-error.js +23 -0
- package/lib/esm/body.js +104 -56
- package/lib/esm/errors/base.js +3 -1
- package/lib/esm/headers.js +116 -131
- package/lib/esm/index.js +145 -190
- package/lib/esm/request.js +42 -41
- package/lib/esm/response.js +19 -4
- package/lib/esm/utils/blob-from.js +2 -98
- package/lib/esm/utils/data-uri.js +23 -0
- package/lib/esm/utils/is.js +7 -3
- package/lib/esm/utils/multipart-parser.js +5 -2
- package/lib/esm/utils/referrer.js +10 -10
- package/lib/esm/utils/soup-helpers.js +22 -0
- package/lib/headers.d.ts +33 -0
- package/lib/headers.js +195 -0
- package/lib/index.d.ts +18 -0
- package/lib/index.js +205 -0
- package/lib/request.d.ts +101 -0
- package/lib/request.js +308 -0
- package/lib/response.d.ts +73 -0
- package/lib/response.js +158 -0
- package/lib/types/index.d.ts +1 -0
- package/lib/types/index.js +1 -0
- package/lib/types/system-error.d.ts +11 -0
- package/lib/types/system-error.js +2 -0
- package/lib/utils/blob-from.d.ts +2 -0
- package/lib/utils/blob-from.js +4 -0
- package/lib/utils/data-uri.d.ts +10 -0
- package/lib/utils/data-uri.js +27 -0
- package/lib/utils/get-search.d.ts +1 -0
- package/lib/utils/get-search.js +8 -0
- package/lib/utils/is-redirect.d.ts +7 -0
- package/lib/utils/is-redirect.js +10 -0
- package/lib/utils/is.d.ts +35 -0
- package/lib/utils/is.js +74 -0
- package/lib/utils/multipart-parser.d.ts +2 -0
- package/lib/utils/multipart-parser.js +396 -0
- package/lib/utils/referrer.d.ts +76 -0
- package/lib/utils/referrer.js +283 -0
- package/lib/utils/soup-helpers.d.ts +12 -0
- package/lib/utils/soup-helpers.js +25 -0
- package/package.json +23 -27
- package/src/body.ts +181 -169
- package/src/errors/base.ts +3 -1
- package/src/headers.ts +155 -202
- package/src/index.spec.ts +268 -3
- package/src/index.ts +199 -312
- package/src/request.ts +84 -75
- package/src/response.ts +48 -18
- package/src/test.mts +1 -1
- package/src/utils/blob-from.ts +4 -164
- package/src/utils/data-uri.ts +29 -0
- package/src/utils/is.ts +15 -15
- package/src/utils/multipart-parser.ts +3 -3
- package/src/utils/referrer.ts +11 -11
- package/src/utils/soup-helpers.ts +37 -0
- package/tsconfig.json +4 -4
- package/tsconfig.tsbuildinfo +1 -0
- package/lib/cjs/body.js +0 -255
- package/lib/cjs/errors/abort-error.js +0 -9
- package/lib/cjs/errors/base.js +0 -17
- package/lib/cjs/errors/fetch-error.js +0 -21
- package/lib/cjs/headers.js +0 -202
- package/lib/cjs/index.js +0 -224
- package/lib/cjs/request.js +0 -281
- package/lib/cjs/response.js +0 -133
- package/lib/cjs/types/index.js +0 -1
- package/lib/cjs/types/system-error.js +0 -1
- package/lib/cjs/utils/blob-from.js +0 -101
- package/lib/cjs/utils/get-search.js +0 -11
- package/lib/cjs/utils/is-redirect.js +0 -7
- package/lib/cjs/utils/is.js +0 -28
- package/lib/cjs/utils/multipart-parser.js +0 -353
- package/lib/cjs/utils/referrer.js +0 -153
- package/test.gjs.js +0 -34758
- package/test.gjs.mjs +0 -53172
- package/test.node.js +0 -1226
- package/test.node.mjs +0 -6273
- package/tsconfig.types.json +0 -8
package/lib/esm/body.js
CHANGED
|
@@ -1,15 +1,24 @@
|
|
|
1
|
-
import { URLSearchParams } from "@gjsify/
|
|
2
|
-
import { Blob } from "
|
|
3
|
-
import { PassThrough, pipeline as pipelineCb, Readable, Stream } from "stream";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { Buffer } from "buffer";
|
|
7
|
-
import { FormData, formDataToBlob } from "formdata-polyfill/esm.min.js";
|
|
1
|
+
import { URLSearchParams } from "@gjsify/url";
|
|
2
|
+
import { Blob } from "./utils/blob-from.js";
|
|
3
|
+
import { PassThrough, pipeline as pipelineCb, Readable, Stream } from "node:stream";
|
|
4
|
+
import { Buffer } from "node:buffer";
|
|
5
|
+
import { FormData, formDataToBlob } from "@gjsify/formdata";
|
|
8
6
|
import { FetchError } from "./errors/fetch-error.js";
|
|
9
7
|
import { FetchBaseError } from "./errors/base.js";
|
|
10
8
|
import { isBlob, isURLSearchParameters } from "./utils/is.js";
|
|
11
|
-
const pipeline =
|
|
12
|
-
|
|
9
|
+
const pipeline = (source, dest) => new Promise((resolve, reject) => {
|
|
10
|
+
pipelineCb(source, dest, (err) => {
|
|
11
|
+
if (err) reject(err);
|
|
12
|
+
else resolve();
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
const INTERNALS = /* @__PURE__ */ Symbol("Body internals");
|
|
16
|
+
function isAnyArrayBuffer(val) {
|
|
17
|
+
return val instanceof ArrayBuffer || typeof SharedArrayBuffer !== "undefined" && val instanceof SharedArrayBuffer;
|
|
18
|
+
}
|
|
19
|
+
function isBoxedPrimitive(val) {
|
|
20
|
+
return val instanceof String || val instanceof Number || val instanceof Boolean || typeof Symbol !== "undefined" && val instanceof Symbol || typeof BigInt !== "undefined" && val instanceof BigInt;
|
|
21
|
+
}
|
|
13
22
|
class Body {
|
|
14
23
|
[INTERNALS] = {
|
|
15
24
|
body: null,
|
|
@@ -21,47 +30,71 @@ class Body {
|
|
|
21
30
|
size = 0;
|
|
22
31
|
constructor(body, options = { size: 0 }) {
|
|
23
32
|
this.size = options.size || 0;
|
|
24
|
-
if (body === null) {
|
|
33
|
+
if (body === null || body === void 0) {
|
|
25
34
|
this[INTERNALS].body = null;
|
|
26
35
|
} else if (isURLSearchParameters(body)) {
|
|
27
36
|
this[INTERNALS].body = Buffer.from(body.toString());
|
|
28
37
|
} else if (isBlob(body)) {
|
|
38
|
+
this[INTERNALS].body = body;
|
|
29
39
|
} else if (Buffer.isBuffer(body)) {
|
|
30
|
-
|
|
40
|
+
this[INTERNALS].body = body;
|
|
41
|
+
} else if (isAnyArrayBuffer(body)) {
|
|
31
42
|
this[INTERNALS].body = Buffer.from(body);
|
|
32
43
|
} else if (ArrayBuffer.isView(body)) {
|
|
33
44
|
this[INTERNALS].body = Buffer.from(body.buffer, body.byteOffset, body.byteLength);
|
|
34
45
|
} else if (body instanceof Readable) {
|
|
35
46
|
this[INTERNALS].body = body;
|
|
36
|
-
} else if (
|
|
37
|
-
this[INTERNALS].body =
|
|
47
|
+
} else if (typeof ReadableStream !== "undefined" && body instanceof ReadableStream) {
|
|
48
|
+
this[INTERNALS].body = readableStreamToReadable(body);
|
|
38
49
|
} else if (body instanceof FormData) {
|
|
39
|
-
|
|
40
|
-
this[INTERNALS].
|
|
50
|
+
const blob = formDataToBlob(body);
|
|
51
|
+
this[INTERNALS].body = blob;
|
|
52
|
+
this[INTERNALS].boundary = blob.type?.split("boundary=")?.[1] ?? "";
|
|
41
53
|
} else if (typeof body === "string") {
|
|
42
54
|
this[INTERNALS].body = Buffer.from(body);
|
|
43
55
|
} else if (body instanceof URLSearchParams) {
|
|
44
56
|
this[INTERNALS].body = Buffer.from(body.toString());
|
|
45
57
|
} else {
|
|
46
58
|
console.warn(`Unknown body type "${typeof body}", try to parse the body to string!`);
|
|
47
|
-
this[INTERNALS].body =
|
|
59
|
+
this[INTERNALS].body = Buffer.from(String(body));
|
|
48
60
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
61
|
+
const b = this[INTERNALS].body;
|
|
62
|
+
if (Buffer.isBuffer(b)) {
|
|
63
|
+
this[INTERNALS].stream = Readable.from(b);
|
|
64
|
+
} else if (isBlob(b)) {
|
|
65
|
+
this[INTERNALS].stream = Readable.from(blobToAsyncIterable(b));
|
|
66
|
+
} else if (b instanceof Readable) {
|
|
67
|
+
this[INTERNALS].stream = b;
|
|
55
68
|
}
|
|
56
|
-
if (
|
|
57
|
-
|
|
69
|
+
if (b instanceof Stream) {
|
|
70
|
+
b.on("error", (error_) => {
|
|
58
71
|
const error = error_ instanceof FetchBaseError ? error_ : new FetchError(`Invalid response body while trying to fetch ${this.url}: ${error_.message}`, "system", error_);
|
|
59
72
|
this[INTERNALS].error = error;
|
|
60
73
|
});
|
|
61
74
|
}
|
|
62
75
|
}
|
|
63
76
|
get body() {
|
|
64
|
-
|
|
77
|
+
const stream = this[INTERNALS].stream;
|
|
78
|
+
if (!stream) return null;
|
|
79
|
+
if (typeof ReadableStream !== "undefined") {
|
|
80
|
+
return new ReadableStream({
|
|
81
|
+
start(controller) {
|
|
82
|
+
stream.on("data", (chunk) => {
|
|
83
|
+
controller.enqueue(chunk instanceof Uint8Array ? chunk : new Uint8Array(chunk));
|
|
84
|
+
});
|
|
85
|
+
stream.on("end", () => {
|
|
86
|
+
controller.close();
|
|
87
|
+
});
|
|
88
|
+
stream.on("error", (err) => {
|
|
89
|
+
controller.error(err);
|
|
90
|
+
});
|
|
91
|
+
},
|
|
92
|
+
cancel() {
|
|
93
|
+
stream.destroy();
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
return null;
|
|
65
98
|
}
|
|
66
99
|
get _stream() {
|
|
67
100
|
return this[INTERNALS].stream;
|
|
@@ -71,8 +104,6 @@ class Body {
|
|
|
71
104
|
}
|
|
72
105
|
/**
|
|
73
106
|
* Decode response as ArrayBuffer
|
|
74
|
-
*
|
|
75
|
-
* @return Promise
|
|
76
107
|
*/
|
|
77
108
|
async arrayBuffer() {
|
|
78
109
|
const { buffer, byteOffset, byteLength } = await consumeBody(this);
|
|
@@ -80,7 +111,7 @@ class Body {
|
|
|
80
111
|
}
|
|
81
112
|
async formData() {
|
|
82
113
|
const ct = this.headers?.get("content-type");
|
|
83
|
-
if (ct
|
|
114
|
+
if (ct?.startsWith("application/x-www-form-urlencoded")) {
|
|
84
115
|
const formData = new FormData();
|
|
85
116
|
const parameters = new URLSearchParams(await this.text());
|
|
86
117
|
for (const [name, value] of parameters) {
|
|
@@ -93,10 +124,7 @@ class Body {
|
|
|
93
124
|
}
|
|
94
125
|
/**
|
|
95
126
|
* Return raw response as Blob
|
|
96
|
-
*
|
|
97
|
-
* @return Promise
|
|
98
127
|
*/
|
|
99
|
-
// @ts-ignore
|
|
100
128
|
async blob() {
|
|
101
129
|
const ct = this.headers?.get("content-type") || this[INTERNALS].body && this[INTERNALS].body.type || "";
|
|
102
130
|
const buf = await this.arrayBuffer();
|
|
@@ -106,8 +134,6 @@ class Body {
|
|
|
106
134
|
}
|
|
107
135
|
/**
|
|
108
136
|
* Decode response as json
|
|
109
|
-
*
|
|
110
|
-
* @return Promise
|
|
111
137
|
*/
|
|
112
138
|
async json() {
|
|
113
139
|
const text = await this.text();
|
|
@@ -115,8 +141,6 @@ class Body {
|
|
|
115
141
|
}
|
|
116
142
|
/**
|
|
117
143
|
* Decode response as text
|
|
118
|
-
*
|
|
119
|
-
* @return Promise
|
|
120
144
|
*/
|
|
121
145
|
async text() {
|
|
122
146
|
const buffer = await consumeBody(this);
|
|
@@ -129,13 +153,7 @@ Object.defineProperties(Body.prototype, {
|
|
|
129
153
|
arrayBuffer: { enumerable: true },
|
|
130
154
|
blob: { enumerable: true },
|
|
131
155
|
json: { enumerable: true },
|
|
132
|
-
text: { enumerable: true }
|
|
133
|
-
data: { get: deprecate(
|
|
134
|
-
() => {
|
|
135
|
-
},
|
|
136
|
-
"data doesn't exist, use json(), text(), arrayBuffer(), or body instead",
|
|
137
|
-
"https://github.com/node-fetch/node-fetch/issues/1000 (response)"
|
|
138
|
-
) }
|
|
156
|
+
text: { enumerable: true }
|
|
139
157
|
});
|
|
140
158
|
async function consumeBody(data) {
|
|
141
159
|
if (data[INTERNALS].disturbed) {
|
|
@@ -165,20 +183,18 @@ async function consumeBody(data) {
|
|
|
165
183
|
accum.push(chunk);
|
|
166
184
|
}
|
|
167
185
|
} catch (error) {
|
|
168
|
-
const
|
|
186
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
187
|
+
const error_ = error instanceof FetchBaseError ? error : new FetchError(`Invalid response body while trying to fetch ${data.url}: ${err.message}`, "system", err);
|
|
169
188
|
throw error_;
|
|
170
189
|
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
return Buffer.from(accum.join(""));
|
|
175
|
-
}
|
|
176
|
-
return Buffer.concat(accum, accumBytes);
|
|
177
|
-
} catch (error) {
|
|
178
|
-
throw new FetchError(`Could not create Buffer from response body for ${data.url}: ${error.message}`, "system", error);
|
|
190
|
+
try {
|
|
191
|
+
if (accum.every((c) => typeof c === "string")) {
|
|
192
|
+
return Buffer.from(accum.join(""));
|
|
179
193
|
}
|
|
180
|
-
|
|
181
|
-
|
|
194
|
+
return Buffer.concat(accum, accumBytes);
|
|
195
|
+
} catch (error) {
|
|
196
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
197
|
+
throw new FetchError(`Could not create Buffer from response body for ${data.url}: ${err.message}`, "system", err);
|
|
182
198
|
}
|
|
183
199
|
}
|
|
184
200
|
const clone = (instance, highWaterMark) => {
|
|
@@ -211,7 +227,7 @@ const extractContentType = (body, request) => {
|
|
|
211
227
|
if (isBlob(body)) {
|
|
212
228
|
return body.type || null;
|
|
213
229
|
}
|
|
214
|
-
if (Buffer.isBuffer(body) ||
|
|
230
|
+
if (Buffer.isBuffer(body) || isAnyArrayBuffer(body) || ArrayBuffer.isView(body)) {
|
|
215
231
|
return null;
|
|
216
232
|
}
|
|
217
233
|
if (body instanceof FormData) {
|
|
@@ -234,8 +250,8 @@ const getTotalBytes = (request) => {
|
|
|
234
250
|
return body.length;
|
|
235
251
|
}
|
|
236
252
|
if (body && typeof body.getLengthSync === "function") {
|
|
237
|
-
const
|
|
238
|
-
return
|
|
253
|
+
const streamBody = body;
|
|
254
|
+
return streamBody.hasKnownLength && streamBody.hasKnownLength() ? streamBody.getLengthSync() : null;
|
|
239
255
|
}
|
|
240
256
|
return null;
|
|
241
257
|
};
|
|
@@ -246,6 +262,38 @@ const writeToStream = async (dest, { body }) => {
|
|
|
246
262
|
await pipeline(body, dest);
|
|
247
263
|
}
|
|
248
264
|
};
|
|
265
|
+
function readableStreamToReadable(webStream) {
|
|
266
|
+
const reader = webStream.getReader();
|
|
267
|
+
return new Readable({
|
|
268
|
+
async read() {
|
|
269
|
+
try {
|
|
270
|
+
const { done, value } = await reader.read();
|
|
271
|
+
if (done) {
|
|
272
|
+
this.push(null);
|
|
273
|
+
} else {
|
|
274
|
+
this.push(Buffer.from(value));
|
|
275
|
+
}
|
|
276
|
+
} catch (err) {
|
|
277
|
+
this.destroy(err);
|
|
278
|
+
}
|
|
279
|
+
},
|
|
280
|
+
destroy(_err, callback) {
|
|
281
|
+
reader.cancel().then(() => callback(null), callback);
|
|
282
|
+
}
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
async function* blobToAsyncIterable(blob) {
|
|
286
|
+
if (typeof blob.stream === "function") {
|
|
287
|
+
const reader = blob.stream().getReader();
|
|
288
|
+
while (true) {
|
|
289
|
+
const { done, value } = await reader.read();
|
|
290
|
+
if (done) break;
|
|
291
|
+
yield value;
|
|
292
|
+
}
|
|
293
|
+
} else {
|
|
294
|
+
yield new Uint8Array(await blob.arrayBuffer());
|
|
295
|
+
}
|
|
296
|
+
}
|
|
249
297
|
export {
|
|
250
298
|
clone,
|
|
251
299
|
Body as default,
|
package/lib/esm/errors/base.js
CHANGED
|
@@ -2,7 +2,9 @@ class FetchBaseError extends Error {
|
|
|
2
2
|
type;
|
|
3
3
|
constructor(message, type) {
|
|
4
4
|
super(message);
|
|
5
|
-
Error.captureStackTrace
|
|
5
|
+
if (typeof Error.captureStackTrace === "function") {
|
|
6
|
+
Error.captureStackTrace(this, this.constructor);
|
|
7
|
+
}
|
|
6
8
|
this.type = type;
|
|
7
9
|
}
|
|
8
10
|
get name() {
|
package/lib/esm/headers.js
CHANGED
|
@@ -1,122 +1,80 @@
|
|
|
1
1
|
import Soup from "@girs/soup-3.0";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class Headers
|
|
8
|
-
|
|
9
|
-
* Headers class
|
|
10
|
-
*
|
|
11
|
-
* @constructor
|
|
12
|
-
* @param init Response headers
|
|
13
|
-
*/
|
|
2
|
+
import { validateHeaderName, validateHeaderValue } from "@gjsify/http";
|
|
3
|
+
const _headers = /* @__PURE__ */ Symbol("Headers.headers");
|
|
4
|
+
function isBoxedPrimitive(val) {
|
|
5
|
+
return val instanceof String || val instanceof Number || val instanceof Boolean || typeof Symbol !== "undefined" && val instanceof Symbol || typeof BigInt !== "undefined" && val instanceof BigInt;
|
|
6
|
+
}
|
|
7
|
+
class Headers {
|
|
8
|
+
[_headers];
|
|
14
9
|
constructor(init) {
|
|
15
|
-
|
|
10
|
+
this[_headers] = /* @__PURE__ */ new Map();
|
|
11
|
+
if (init == null) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
16
14
|
if (init instanceof Headers) {
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
result.push(...values.map((value) => [name, value]));
|
|
15
|
+
for (const [name, values] of init[_headers]) {
|
|
16
|
+
this[_headers].set(name, [...values]);
|
|
20
17
|
}
|
|
21
|
-
|
|
22
|
-
}
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
if (typeof init === "object" && !isBoxedPrimitive(init)) {
|
|
23
21
|
const method = init[Symbol.iterator];
|
|
24
22
|
if (method == null) {
|
|
25
|
-
|
|
23
|
+
for (const [name, value] of Object.entries(init)) {
|
|
24
|
+
validateHeaderName(name);
|
|
25
|
+
validateHeaderValue(name, String(value));
|
|
26
|
+
this.append(name, String(value));
|
|
27
|
+
}
|
|
26
28
|
} else {
|
|
27
29
|
if (typeof method !== "function") {
|
|
28
30
|
throw new TypeError("Header pairs must be iterable");
|
|
29
31
|
}
|
|
30
|
-
|
|
31
|
-
if (typeof pair !== "object" ||
|
|
32
|
+
for (const pair of init) {
|
|
33
|
+
if (typeof pair !== "object" || isBoxedPrimitive(pair)) {
|
|
32
34
|
throw new TypeError("Each header pair must be an iterable object");
|
|
33
35
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
if (pair.length !== 2) {
|
|
36
|
+
const arr = [...pair];
|
|
37
|
+
if (arr.length !== 2) {
|
|
37
38
|
throw new TypeError("Each header pair must be a name/value tuple");
|
|
38
39
|
}
|
|
39
|
-
|
|
40
|
-
|
|
40
|
+
validateHeaderName(arr[0]);
|
|
41
|
+
validateHeaderValue(arr[0], String(arr[1]));
|
|
42
|
+
this.append(arr[0], String(arr[1]));
|
|
43
|
+
}
|
|
41
44
|
}
|
|
42
45
|
} else {
|
|
43
|
-
throw new TypeError(
|
|
46
|
+
throw new TypeError(
|
|
47
|
+
"Failed to construct 'Headers': The provided value is not of type '(sequence<sequence<ByteString>> or record<ByteString, ByteString>)'"
|
|
48
|
+
);
|
|
44
49
|
}
|
|
45
|
-
result = result.length > 0 ? result.map(([name, value]) => {
|
|
46
|
-
validateHeaderName(name);
|
|
47
|
-
validateHeaderValue(name, String(value));
|
|
48
|
-
return [String(name).toLowerCase(), String(value)];
|
|
49
|
-
}) : void 0;
|
|
50
|
-
super(result);
|
|
51
|
-
return new Proxy(this, {
|
|
52
|
-
get(target, p, receiver) {
|
|
53
|
-
switch (p) {
|
|
54
|
-
case "append":
|
|
55
|
-
case "set":
|
|
56
|
-
return (name, value) => {
|
|
57
|
-
validateHeaderName(name);
|
|
58
|
-
validateHeaderValue(name, String(value));
|
|
59
|
-
return URLSearchParams.prototype[p].call(
|
|
60
|
-
target,
|
|
61
|
-
String(name).toLowerCase(),
|
|
62
|
-
String(value)
|
|
63
|
-
);
|
|
64
|
-
};
|
|
65
|
-
case "delete":
|
|
66
|
-
case "has":
|
|
67
|
-
case "getAll":
|
|
68
|
-
return (name) => {
|
|
69
|
-
validateHeaderName(name);
|
|
70
|
-
return URLSearchParams.prototype[p].call(
|
|
71
|
-
target,
|
|
72
|
-
String(name).toLowerCase()
|
|
73
|
-
);
|
|
74
|
-
};
|
|
75
|
-
case "keys":
|
|
76
|
-
return () => {
|
|
77
|
-
target.sort();
|
|
78
|
-
return new Set(URLSearchParams.prototype.keys.call(target)).keys();
|
|
79
|
-
};
|
|
80
|
-
default:
|
|
81
|
-
return Reflect.get(target, p, receiver);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
});
|
|
85
50
|
}
|
|
86
|
-
|
|
87
|
-
|
|
51
|
+
append(name, value) {
|
|
52
|
+
validateHeaderName(name);
|
|
53
|
+
validateHeaderValue(name, value);
|
|
54
|
+
const lowerName = String(name).toLowerCase();
|
|
55
|
+
const strValue = String(value);
|
|
56
|
+
const existing = this[_headers].get(lowerName);
|
|
57
|
+
if (existing) {
|
|
58
|
+
existing.push(strValue);
|
|
59
|
+
} else {
|
|
60
|
+
this[_headers].set(lowerName, [strValue]);
|
|
61
|
+
}
|
|
88
62
|
}
|
|
89
|
-
|
|
90
|
-
|
|
63
|
+
set(name, value) {
|
|
64
|
+
validateHeaderName(name);
|
|
65
|
+
validateHeaderValue(name, value);
|
|
66
|
+
const lowerName = String(name).toLowerCase();
|
|
67
|
+
this[_headers].set(lowerName, [String(value)]);
|
|
91
68
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
for (const header in this.entries()) {
|
|
95
|
-
soupHeaders.append(header, this.get(header));
|
|
96
|
-
}
|
|
97
|
-
return soupHeaders;
|
|
69
|
+
delete(name) {
|
|
70
|
+
this[_headers].delete(String(name).toLowerCase());
|
|
98
71
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
const headers = new Headers();
|
|
102
|
-
if (type === Soup.MessageHeadersType.RESPONSE) {
|
|
103
|
-
soupHeaders = message.get_response_headers();
|
|
104
|
-
} else if (type === Soup.MessageHeadersType.REQUEST) {
|
|
105
|
-
soupHeaders = message.get_request_headers();
|
|
106
|
-
} else {
|
|
107
|
-
for (const header in message.get_request_headers()) {
|
|
108
|
-
headers.append(header, soupHeaders[header]);
|
|
109
|
-
}
|
|
110
|
-
soupHeaders = message.get_response_headers();
|
|
111
|
-
}
|
|
112
|
-
for (const header in soupHeaders) {
|
|
113
|
-
headers.append(header, soupHeaders[header]);
|
|
114
|
-
}
|
|
115
|
-
return headers;
|
|
72
|
+
has(name) {
|
|
73
|
+
return this[_headers].has(String(name).toLowerCase());
|
|
116
74
|
}
|
|
117
75
|
get(name) {
|
|
118
|
-
const values = this.
|
|
119
|
-
if (values.length === 0) {
|
|
76
|
+
const values = this[_headers].get(String(name).toLowerCase());
|
|
77
|
+
if (!values || values.length === 0) {
|
|
120
78
|
return null;
|
|
121
79
|
}
|
|
122
80
|
let value = values.join(", ");
|
|
@@ -125,19 +83,32 @@ class Headers extends URLSearchParams {
|
|
|
125
83
|
}
|
|
126
84
|
return value;
|
|
127
85
|
}
|
|
128
|
-
|
|
86
|
+
getAll(name) {
|
|
87
|
+
return this[_headers].get(String(name).toLowerCase()) ?? [];
|
|
88
|
+
}
|
|
89
|
+
getSetCookie() {
|
|
90
|
+
return this[_headers].get("set-cookie") ?? [];
|
|
91
|
+
}
|
|
92
|
+
forEach(callback, thisArg) {
|
|
129
93
|
for (const name of this.keys()) {
|
|
130
94
|
Reflect.apply(callback, thisArg, [this.get(name), name, this]);
|
|
131
95
|
}
|
|
132
96
|
}
|
|
97
|
+
*keys() {
|
|
98
|
+
const sorted = [...this[_headers].keys()].sort();
|
|
99
|
+
const seen = /* @__PURE__ */ new Set();
|
|
100
|
+
for (const key of sorted) {
|
|
101
|
+
if (!seen.has(key)) {
|
|
102
|
+
seen.add(key);
|
|
103
|
+
yield key;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
133
107
|
*values() {
|
|
134
108
|
for (const name of this.keys()) {
|
|
135
109
|
yield this.get(name);
|
|
136
110
|
}
|
|
137
111
|
}
|
|
138
|
-
/**
|
|
139
|
-
*
|
|
140
|
-
*/
|
|
141
112
|
*entries() {
|
|
142
113
|
for (const name of this.keys()) {
|
|
143
114
|
yield [name, this.get(name)];
|
|
@@ -146,29 +117,62 @@ class Headers extends URLSearchParams {
|
|
|
146
117
|
[Symbol.iterator]() {
|
|
147
118
|
return this.entries();
|
|
148
119
|
}
|
|
120
|
+
get [Symbol.toStringTag]() {
|
|
121
|
+
return "Headers";
|
|
122
|
+
}
|
|
123
|
+
toString() {
|
|
124
|
+
return Object.prototype.toString.call(this);
|
|
125
|
+
}
|
|
149
126
|
/**
|
|
150
|
-
* Node-fetch non-spec method
|
|
151
|
-
* returning all headers and their values as array
|
|
127
|
+
* Node-fetch non-spec method: return all headers and their values as arrays.
|
|
152
128
|
*/
|
|
153
129
|
raw() {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
}
|
|
130
|
+
const result = {};
|
|
131
|
+
for (const name of this.keys()) {
|
|
132
|
+
result[name] = this.getAll(name);
|
|
133
|
+
}
|
|
134
|
+
return result;
|
|
158
135
|
}
|
|
159
136
|
/**
|
|
160
|
-
*
|
|
137
|
+
* Append all headers to a Soup.Message for sending.
|
|
161
138
|
*/
|
|
162
|
-
|
|
163
|
-
|
|
139
|
+
_appendToSoupMessage(message, type = Soup.MessageHeadersType.REQUEST) {
|
|
140
|
+
const soupHeaders = message ? message.get_request_headers() : new Soup.MessageHeaders(type);
|
|
141
|
+
for (const [name, value] of this.entries()) {
|
|
142
|
+
soupHeaders.append(name, value);
|
|
143
|
+
}
|
|
144
|
+
return soupHeaders;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Create a Headers instance from a Soup.Message's headers.
|
|
148
|
+
*/
|
|
149
|
+
static _newFromSoupMessage(message, type = Soup.MessageHeadersType.RESPONSE) {
|
|
150
|
+
const headers = new Headers();
|
|
151
|
+
let soupHeaders;
|
|
152
|
+
if (type === Soup.MessageHeadersType.RESPONSE) {
|
|
153
|
+
soupHeaders = message.get_response_headers();
|
|
154
|
+
} else {
|
|
155
|
+
soupHeaders = message.get_request_headers();
|
|
156
|
+
}
|
|
157
|
+
soupHeaders.foreach((name, value) => {
|
|
158
|
+
headers.append(name, value);
|
|
159
|
+
});
|
|
160
|
+
return headers;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* For better console.log(headers)
|
|
164
|
+
*/
|
|
165
|
+
[/* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom")]() {
|
|
166
|
+
const result = {};
|
|
167
|
+
for (const key of this.keys()) {
|
|
164
168
|
const values = this.getAll(key);
|
|
165
169
|
if (key === "host") {
|
|
166
170
|
result[key] = values[0];
|
|
167
171
|
} else {
|
|
168
172
|
result[key] = values.length > 1 ? values : values[0];
|
|
169
173
|
}
|
|
170
|
-
|
|
171
|
-
|
|
174
|
+
}
|
|
175
|
+
return result;
|
|
172
176
|
}
|
|
173
177
|
}
|
|
174
178
|
Object.defineProperties(
|
|
@@ -178,25 +182,6 @@ Object.defineProperties(
|
|
|
178
182
|
return result;
|
|
179
183
|
}, {})
|
|
180
184
|
);
|
|
181
|
-
function fromRawHeaders(headers = []) {
|
|
182
|
-
return new Headers(
|
|
183
|
-
headers.reduce((result, value, index, array) => {
|
|
184
|
-
if (index % 2 === 0) {
|
|
185
|
-
result.push(array.slice(index, index + 2));
|
|
186
|
-
}
|
|
187
|
-
return result;
|
|
188
|
-
}, []).filter(([name, value]) => {
|
|
189
|
-
try {
|
|
190
|
-
validateHeaderName(name);
|
|
191
|
-
validateHeaderValue(name, String(value));
|
|
192
|
-
return true;
|
|
193
|
-
} catch {
|
|
194
|
-
return false;
|
|
195
|
-
}
|
|
196
|
-
})
|
|
197
|
-
);
|
|
198
|
-
}
|
|
199
185
|
export {
|
|
200
|
-
Headers as default
|
|
201
|
-
fromRawHeaders
|
|
186
|
+
Headers as default
|
|
202
187
|
};
|