@gby/got-scraping 4.1.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/dist/index.js ADDED
@@ -0,0 +1,1117 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
4
+ var __publicField = (obj, key, value) => {
5
+ __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
6
+ return value;
7
+ };
8
+
9
+ // src/index.ts
10
+ import http3 from "node:http";
11
+ import https2 from "node:https";
12
+ import { got as originalGot, Options as Options8 } from "got";
13
+ import { HeaderGenerator as HeaderGenerator2 } from "header-generator";
14
+
15
+ // src/agent/transform-headers-agent.ts
16
+ import { HeaderGenerator } from "header-generator";
17
+ import { OutgoingMessage } from "node:http";
18
+
19
+ // src/agent/wrapped-agent.ts
20
+ import "node:http";
21
+ var _WrappedAgent = class _WrappedAgent {
22
+ constructor(agent) {
23
+ __publicField(this, "agent");
24
+ this.agent = agent;
25
+ }
26
+ addRequest(request, options) {
27
+ this.agent.addRequest(request, options);
28
+ }
29
+ get keepAlive() {
30
+ return this.agent.keepAlive;
31
+ }
32
+ get maxSockets() {
33
+ return this.agent.maxSockets;
34
+ }
35
+ get options() {
36
+ return this.agent.options;
37
+ }
38
+ get defaultPort() {
39
+ return this.agent.defaultPort;
40
+ }
41
+ get protocol() {
42
+ return this.agent.protocol;
43
+ }
44
+ destroy() {
45
+ this.agent.destroy();
46
+ }
47
+ // Let's implement `HttpAgent` so we don't have to
48
+ // type `WrappedAgent as unknown as HttpAgent`
49
+ get maxFreeSockets() {
50
+ return this.agent.maxFreeSockets;
51
+ }
52
+ get maxTotalSockets() {
53
+ return this.agent.maxTotalSockets;
54
+ }
55
+ get freeSockets() {
56
+ return this.agent.freeSockets;
57
+ }
58
+ get sockets() {
59
+ return this.agent.sockets;
60
+ }
61
+ get requests() {
62
+ return this.agent.requests;
63
+ }
64
+ on(eventName, listener) {
65
+ this.agent.on(eventName, listener);
66
+ return this;
67
+ }
68
+ once(eventName, listener) {
69
+ this.agent.once(eventName, listener);
70
+ return this;
71
+ }
72
+ off(eventName, listener) {
73
+ this.agent.off(eventName, listener);
74
+ return this;
75
+ }
76
+ addListener(eventName, listener) {
77
+ this.agent.addListener(eventName, listener);
78
+ return this;
79
+ }
80
+ removeListener(eventName, listener) {
81
+ this.agent.removeListener(eventName, listener);
82
+ return this;
83
+ }
84
+ removeAllListeners(eventName) {
85
+ this.agent.removeAllListeners(eventName);
86
+ return this;
87
+ }
88
+ setMaxListeners(n) {
89
+ this.agent.setMaxListeners(n);
90
+ return this;
91
+ }
92
+ getMaxListeners() {
93
+ return this.agent.getMaxListeners();
94
+ }
95
+ listeners(eventName) {
96
+ return this.agent.listeners(eventName);
97
+ }
98
+ rawListeners(eventName) {
99
+ return this.agent.rawListeners(eventName);
100
+ }
101
+ emit(eventName, ...args) {
102
+ return this.agent.emit(eventName, ...args);
103
+ }
104
+ eventNames() {
105
+ return this.agent.eventNames();
106
+ }
107
+ listenerCount(eventName) {
108
+ return this.agent.listenerCount(eventName);
109
+ }
110
+ prependListener(eventName, listener) {
111
+ this.agent.prependListener(eventName, listener);
112
+ return this;
113
+ }
114
+ prependOnceListener(eventName, listener) {
115
+ this.agent.prependOnceListener(eventName, listener);
116
+ return this;
117
+ }
118
+ createConnection(options, callback) {
119
+ return this.agent.createConnection(options, callback);
120
+ }
121
+ keepSocketAlive(socket) {
122
+ this.agent.keepSocketAlive(socket);
123
+ }
124
+ reuseSocket(socket, request) {
125
+ this.agent.reuseSocket(socket, request);
126
+ }
127
+ getName(options) {
128
+ return this.agent.getName(options);
129
+ }
130
+ };
131
+ __name(_WrappedAgent, "WrappedAgent");
132
+ var WrappedAgent = _WrappedAgent;
133
+
134
+ // src/agent/transform-headers-agent.ts
135
+ var { _storeHeader } = OutgoingMessage.prototype;
136
+ var generator = new HeaderGenerator();
137
+ var _TransformHeadersAgent = class _TransformHeadersAgent extends WrappedAgent {
138
+ // Rewritten from https://github.com/nodejs/node/blob/533cafcf7e3ab72e98a2478bc69aedfdf06d3a5e/lib/_http_outgoing.js#L442-L479
139
+ /**
140
+ * Transforms the request via header normalization.
141
+ */
142
+ transformRequest(request, { sortHeaders }) {
143
+ const headers = {};
144
+ const hasConnection = request.hasHeader("connection");
145
+ const hasContentLength = request.hasHeader("content-length");
146
+ const hasTransferEncoding = request.hasHeader("transfer-encoding");
147
+ const hasTrailer = request.hasHeader("trailer");
148
+ const keys = request.getHeaderNames();
149
+ for (const key of keys) {
150
+ if (key.toLowerCase().startsWith("x-")) {
151
+ headers[key] = request.getHeader(key);
152
+ } else {
153
+ headers[this.toPascalCase(key)] = request.getHeader(key);
154
+ }
155
+ if (sortHeaders) {
156
+ request.removeHeader(key);
157
+ }
158
+ }
159
+ const typedRequest = request;
160
+ if (!hasConnection) {
161
+ const shouldSendKeepAlive = request.shouldKeepAlive && (hasContentLength || request.useChunkedEncodingByDefault || typedRequest.agent);
162
+ if (shouldSendKeepAlive) {
163
+ headers.Connection = "keep-alive";
164
+ } else {
165
+ headers.Connection = "close";
166
+ }
167
+ }
168
+ if (!hasContentLength && !hasTransferEncoding) {
169
+ if (!hasTrailer && !typedRequest._removedContLen && typeof typedRequest._contentLength === "number") {
170
+ headers["Content-Length"] = typedRequest._contentLength;
171
+ } else if (!typedRequest._removedTE) {
172
+ headers["Transfer-Encoding"] = "chunked";
173
+ }
174
+ }
175
+ const transformedHeaders = sortHeaders ? generator.orderHeaders(headers) : headers;
176
+ for (const [key, value] of Object.entries(transformedHeaders)) {
177
+ request.setHeader(key, value);
178
+ }
179
+ }
180
+ addRequest(request, options) {
181
+ const typedRequest = request;
182
+ typedRequest._storeHeader = (...args) => {
183
+ this.transformRequest(request, { sortHeaders: true });
184
+ return _storeHeader.call(request, ...args);
185
+ };
186
+ options.secureEndpoint = options.protocol === "https:";
187
+ return super.addRequest(request, options);
188
+ }
189
+ toPascalCase(header) {
190
+ return header.split("-").map((part) => {
191
+ return part[0].toUpperCase() + part.slice(1).toLowerCase();
192
+ }).join("-");
193
+ }
194
+ };
195
+ __name(_TransformHeadersAgent, "TransformHeadersAgent");
196
+ var TransformHeadersAgent = _TransformHeadersAgent;
197
+
198
+ // src/hooks/browser-headers.ts
199
+ import "got";
200
+ import http22 from "http2-wrapper";
201
+ import "node:url";
202
+
203
+ // src/resolve-protocol.ts
204
+ import { isIPv6 as isIPv62 } from "node:net";
205
+ import tls2 from "node:tls";
206
+ import { URL as URL3 } from "node:url";
207
+ import "got";
208
+ import { auto as auto2 } from "http2-wrapper";
209
+ import QuickLRU from "quick-lru";
210
+
211
+ // src/hooks/proxy.ts
212
+ import "got";
213
+ import http2, { auto } from "http2-wrapper";
214
+ import { URL as URL2 } from "node:url";
215
+
216
+ // src/agent/h1-proxy-agent.ts
217
+ import http from "node:http";
218
+ import https from "node:https";
219
+ import { isIPv6 } from "node:net";
220
+ import tls from "node:tls";
221
+ import { URL } from "node:url";
222
+
223
+ // src/auth.ts
224
+ function buildBasicAuthHeader(url) {
225
+ if (!url.username && !url.password) {
226
+ return null;
227
+ }
228
+ const username = decodeURIComponent(url.username ?? "");
229
+ const password = decodeURIComponent(url.password ?? "");
230
+ const basic = Buffer.from(`${username}:${password}`).toString("base64");
231
+ return `Basic ${basic}`;
232
+ }
233
+ __name(buildBasicAuthHeader, "buildBasicAuthHeader");
234
+
235
+ // src/agent/h1-proxy-agent.ts
236
+ var initialize = /* @__PURE__ */ __name((self, options) => {
237
+ self.proxy = typeof options.proxy === "string" ? new URL(options.proxy) : options.proxy;
238
+ }, "initialize");
239
+ var getPort = /* @__PURE__ */ __name((url) => {
240
+ if (url.port !== "") {
241
+ return Number(url.port);
242
+ }
243
+ if (url.protocol === "http:") {
244
+ return 80;
245
+ }
246
+ if (url.protocol === "https:") {
247
+ return 443;
248
+ }
249
+ throw new Error(`Unexpected protocol: ${url.protocol}`);
250
+ }, "getPort");
251
+ var _HttpRegularProxyAgent = class _HttpRegularProxyAgent extends http.Agent {
252
+ constructor(options) {
253
+ super(options);
254
+ __publicField(this, "proxy");
255
+ initialize(this, options);
256
+ }
257
+ addRequest(request, options) {
258
+ if (options.socketPath) {
259
+ super.addRequest(request, options);
260
+ return;
261
+ }
262
+ let hostport = `${options.host}:${options.port}`;
263
+ if (isIPv6(options.host)) {
264
+ hostport = `[${options.host}]:${options.port}`;
265
+ }
266
+ const url = new URL(`${request.protocol}//${hostport}${request.path}`);
267
+ options = {
268
+ ...options,
269
+ host: this.proxy.hostname,
270
+ port: getPort(this.proxy)
271
+ };
272
+ request.path = url.href;
273
+ const basic = buildBasicAuthHeader(this.proxy);
274
+ if (basic) {
275
+ request.setHeader("proxy-authorization", basic);
276
+ }
277
+ super.addRequest(request, options);
278
+ }
279
+ };
280
+ __name(_HttpRegularProxyAgent, "HttpRegularProxyAgent");
281
+ var HttpRegularProxyAgent = _HttpRegularProxyAgent;
282
+ var _HttpProxyAgent = class _HttpProxyAgent extends http.Agent {
283
+ constructor(options) {
284
+ super(options);
285
+ __publicField(this, "proxy");
286
+ initialize(this, options);
287
+ }
288
+ // @ts-expect-error New @types/node patch has narrower types than the originally exported got-scraping interface
289
+ createConnection(options, callback) {
290
+ if (options.path) {
291
+ super.createConnection(options, callback);
292
+ return;
293
+ }
294
+ const fn = this.proxy.protocol === "https:" ? https.request : http.request;
295
+ let hostport = `${options.host}:${options.port}`;
296
+ if (isIPv6(options.host)) {
297
+ hostport = `[${options.host}]:${options.port}`;
298
+ }
299
+ const headers = {
300
+ host: hostport
301
+ };
302
+ const basic = buildBasicAuthHeader(this.proxy);
303
+ if (basic) {
304
+ headers["proxy-authorization"] = basic;
305
+ headers.authorization = basic;
306
+ }
307
+ const connectRequest = fn(this.proxy, {
308
+ method: "CONNECT",
309
+ headers,
310
+ path: hostport,
311
+ agent: false,
312
+ rejectUnauthorized: false
313
+ });
314
+ connectRequest.once("connect", (response, socket, head) => {
315
+ if (head.length > 0 || response.statusCode !== 200) {
316
+ socket.destroy();
317
+ const error = new Error(`The proxy responded with ${response.statusCode} ${response.statusMessage}: ${head.toString()}`);
318
+ callback(error);
319
+ return;
320
+ }
321
+ if (options.protocol === "https:") {
322
+ callback(void 0, tls.connect({
323
+ ...options,
324
+ socket
325
+ }));
326
+ return;
327
+ }
328
+ callback(void 0, socket);
329
+ });
330
+ connectRequest.once("error", (error) => {
331
+ callback(error);
332
+ });
333
+ connectRequest.end();
334
+ }
335
+ };
336
+ __name(_HttpProxyAgent, "HttpProxyAgent");
337
+ var HttpProxyAgent = _HttpProxyAgent;
338
+ var _HttpsProxyAgent = class _HttpsProxyAgent extends https.Agent {
339
+ constructor(options) {
340
+ super(options);
341
+ __publicField(this, "proxy");
342
+ initialize(this, options);
343
+ }
344
+ // @ts-expect-error New @types/node patch has narrower types than the originally exported got-scraping interface
345
+ createConnection(options, callback) {
346
+ HttpProxyAgent.prototype.createConnection.call(this, options, callback);
347
+ }
348
+ };
349
+ __name(_HttpsProxyAgent, "HttpsProxyAgent");
350
+ var HttpsProxyAgent = _HttpsProxyAgent;
351
+
352
+ // src/hooks/proxy.ts
353
+ var {
354
+ HttpOverHttp2,
355
+ HttpsOverHttp2,
356
+ Http2OverHttp2,
357
+ Http2OverHttps,
358
+ Http2OverHttp
359
+ } = http2.proxies;
360
+ async function proxyHook(options) {
361
+ const { context: { proxyUrl } } = options;
362
+ if (proxyUrl) {
363
+ const parsedProxy = new URL2(proxyUrl);
364
+ validateProxyProtocol(parsedProxy.protocol);
365
+ options.agent = await getAgents(parsedProxy, options.https.rejectUnauthorized);
366
+ }
367
+ }
368
+ __name(proxyHook, "proxyHook");
369
+ var _ProxyError = class _ProxyError extends Error {
370
+ };
371
+ __name(_ProxyError, "ProxyError");
372
+ var ProxyError = _ProxyError;
373
+ function validateProxyProtocol(protocol) {
374
+ const isSupported = protocol === "http:" || protocol === "https:";
375
+ if (!isSupported) {
376
+ throw new ProxyError(`Proxy URL protocol "${protocol}" is not supported. Please use HTTP or HTTPS.`);
377
+ }
378
+ }
379
+ __name(validateProxyProtocol, "validateProxyProtocol");
380
+ async function getAgents(parsedProxyUrl, rejectUnauthorized) {
381
+ const headers = {};
382
+ const basic = buildBasicAuthHeader(parsedProxyUrl);
383
+ if (basic) {
384
+ headers.authorization = basic;
385
+ headers["proxy-authorization"] = basic;
386
+ }
387
+ const wrapperOptions = {
388
+ proxyOptions: {
389
+ url: parsedProxyUrl,
390
+ headers,
391
+ // Based on the got https.rejectUnauthorized option
392
+ rejectUnauthorized
393
+ },
394
+ // The sockets won't be reused, no need to keep them
395
+ maxFreeSockets: 0,
396
+ maxEmptySessions: 0
397
+ };
398
+ const nativeOptions = {
399
+ proxy: parsedProxyUrl,
400
+ // The sockets won't be reused, no need to keep them
401
+ maxFreeSockets: 0
402
+ };
403
+ let agent;
404
+ if (parsedProxyUrl.protocol === "https:") {
405
+ let alpnProtocol = "http/1.1";
406
+ try {
407
+ const result = await auto.resolveProtocol({
408
+ host: parsedProxyUrl.hostname,
409
+ port: parsedProxyUrl.port,
410
+ rejectUnauthorized,
411
+ ALPNProtocols: ["h2", "http/1.1"],
412
+ servername: parsedProxyUrl.hostname
413
+ });
414
+ alpnProtocol = result.alpnProtocol;
415
+ } catch {
416
+ }
417
+ const proxyIsHttp2 = alpnProtocol === "h2";
418
+ if (proxyIsHttp2) {
419
+ agent = {
420
+ http: new TransformHeadersAgent(new HttpOverHttp2(wrapperOptions)),
421
+ https: new TransformHeadersAgent(new HttpsOverHttp2(wrapperOptions)),
422
+ http2: new Http2OverHttp2(wrapperOptions)
423
+ };
424
+ } else {
425
+ agent = {
426
+ // @ts-expect-error New @types/node patch has narrower types than the originally exported got-scraping interface
427
+ http: new TransformHeadersAgent(new HttpProxyAgent(nativeOptions)),
428
+ // @ts-expect-error New @types/node patch has narrower types than the originally exported got-scraping interface
429
+ https: new TransformHeadersAgent(new HttpsProxyAgent(nativeOptions)),
430
+ http2: new Http2OverHttps(wrapperOptions)
431
+ };
432
+ }
433
+ } else {
434
+ agent = {
435
+ http: new TransformHeadersAgent(new HttpRegularProxyAgent(nativeOptions)),
436
+ // @ts-expect-error New @types/node patch has narrower types than the originally exported got-scraping interface
437
+ https: new TransformHeadersAgent(new HttpsProxyAgent(nativeOptions)),
438
+ http2: new Http2OverHttp(wrapperOptions)
439
+ };
440
+ }
441
+ return agent;
442
+ }
443
+ __name(getAgents, "getAgents");
444
+
445
+ // src/resolve-protocol.ts
446
+ var connect = /* @__PURE__ */ __name(async (proxyUrl, options, callback) => new Promise((resolve, reject) => {
447
+ let host = `${options.host}:${options.port}`;
448
+ if (isIPv62(options.host)) {
449
+ host = `[${options.host}]:${options.port}`;
450
+ }
451
+ void (async () => {
452
+ try {
453
+ const headers = {
454
+ host
455
+ };
456
+ const url = new URL3(proxyUrl);
457
+ const basic = buildBasicAuthHeader(url);
458
+ if (basic) {
459
+ headers.authorization = basic;
460
+ headers["proxy-authorization"] = basic;
461
+ }
462
+ const request = await auto2(url, {
463
+ method: "CONNECT",
464
+ headers,
465
+ path: host,
466
+ // TODO: this property doesn't exist according to the types
467
+ pathname: host,
468
+ rejectUnauthorized: false
469
+ });
470
+ request.end();
471
+ request.once("error", reject);
472
+ request.once("connect", (response, socket, head) => {
473
+ if (response.statusCode !== 200 || head.length > 0) {
474
+ reject(new ProxyError(`Proxy responded with ${response.statusCode} ${response.statusMessage}: ${head.length} bytes.
475
+
476
+ Below is the first 100 bytes of the proxy response body:
477
+ ${head.toString("utf8", 0, 100)}`, { cause: head.toString("utf8") }));
478
+ socket.destroy();
479
+ return;
480
+ }
481
+ const tlsSocket = tls2.connect({
482
+ ...options,
483
+ socket
484
+ }, callback);
485
+ resolve(tlsSocket);
486
+ });
487
+ } catch (error) {
488
+ reject(error);
489
+ }
490
+ })();
491
+ }), "connect");
492
+ var createCaches = /* @__PURE__ */ __name(() => ({
493
+ protocolCache: new QuickLRU({ maxSize: 1e3 }),
494
+ resolveAlpnQueue: /* @__PURE__ */ new Map()
495
+ }), "createCaches");
496
+ var defaults = createCaches();
497
+ var createResolveProtocol = /* @__PURE__ */ __name((proxyUrl, sessionData, timeout) => {
498
+ let { protocolCache, resolveAlpnQueue } = defaults;
499
+ if (sessionData) {
500
+ if (!sessionData.protocolCache || !sessionData.resolveAlpnQueue) {
501
+ Object.assign(sessionData, createCaches());
502
+ }
503
+ protocolCache = sessionData.protocolCache;
504
+ resolveAlpnQueue = sessionData.resolveAlpnQueue;
505
+ }
506
+ const connectWithProxy = /* @__PURE__ */ __name(async (pOptions, pCallback) => {
507
+ return connect(proxyUrl, pOptions, pCallback);
508
+ }, "connectWithProxy");
509
+ const resolveProtocol = auto2.createResolveProtocol(
510
+ protocolCache,
511
+ resolveAlpnQueue,
512
+ connectWithProxy
513
+ );
514
+ return async (...args) => resolveProtocol({
515
+ ...args[0],
516
+ timeout
517
+ });
518
+ }, "createResolveProtocol");
519
+
520
+ // src/hooks/browser-headers.ts
521
+ function mergeHeaders(original, overrides) {
522
+ const fixedHeaders = /* @__PURE__ */ new Map();
523
+ for (const entry of Object.entries(original)) {
524
+ fixedHeaders.set(entry[0].toLowerCase(), entry);
525
+ }
526
+ for (const entry of Object.entries(overrides)) {
527
+ fixedHeaders.set(entry[0].toLowerCase(), entry);
528
+ }
529
+ return Object.fromEntries(fixedHeaders.values());
530
+ }
531
+ __name(mergeHeaders, "mergeHeaders");
532
+ var getResolveProtocolFunction = /* @__PURE__ */ __name((options, proxyUrl, sessionData) => {
533
+ const { resolveProtocol } = options;
534
+ if (resolveProtocol) {
535
+ return resolveProtocol;
536
+ }
537
+ if (proxyUrl) {
538
+ return createResolveProtocol(proxyUrl, sessionData, Math.min(options?.timeout?.connect ?? 6e4, options?.timeout?.request ?? 6e4));
539
+ }
540
+ return (...args) => http22.auto.resolveProtocol({
541
+ ...args[0],
542
+ timeout: Math.min(options?.timeout?.connect ?? 6e4, options?.timeout?.request ?? 6e4)
543
+ });
544
+ }, "getResolveProtocolFunction");
545
+ async function browserHeadersHook(options) {
546
+ const { context } = options;
547
+ const {
548
+ headerGeneratorOptions,
549
+ useHeaderGenerator,
550
+ headerGenerator,
551
+ proxyUrl
552
+ } = context;
553
+ const sessionData = context.sessionData;
554
+ if (!useHeaderGenerator || !headerGenerator)
555
+ return;
556
+ const createHeadersPair = /* @__PURE__ */ __name(() => ({
557
+ 1: headerGenerator.getHeaders({
558
+ httpVersion: "1",
559
+ ...headerGeneratorOptions
560
+ }),
561
+ 2: headerGenerator.getHeaders({
562
+ httpVersion: "2",
563
+ ...headerGeneratorOptions
564
+ })
565
+ }), "createHeadersPair");
566
+ const url = options.url;
567
+ const resolveProtocol = getResolveProtocolFunction(options, proxyUrl, sessionData);
568
+ let alpnProtocol;
569
+ if (url.protocol === "https:") {
570
+ alpnProtocol = (await resolveProtocol({
571
+ host: url.hostname,
572
+ port: url.port || 443,
573
+ rejectUnauthorized: false,
574
+ ALPNProtocols: ["h2", "http/1.1"],
575
+ servername: url.hostname
576
+ })).alpnProtocol;
577
+ }
578
+ const httpVersion = alpnProtocol === "h2" ? "2" : "1";
579
+ let generatedHeaders;
580
+ if (sessionData) {
581
+ if (!sessionData.headers) {
582
+ sessionData.headers = createHeadersPair();
583
+ }
584
+ generatedHeaders = sessionData.headers[httpVersion];
585
+ } else {
586
+ generatedHeaders = headerGenerator.getHeaders({
587
+ httpVersion,
588
+ ...headerGeneratorOptions
589
+ });
590
+ }
591
+ if (!options.decompress) {
592
+ for (const key of Object.keys(generatedHeaders)) {
593
+ if (key.toLowerCase() === "accept-encoding") {
594
+ delete generatedHeaders[key];
595
+ }
596
+ }
597
+ }
598
+ options.headers = mergeHeaders(generatedHeaders, options.headers);
599
+ }
600
+ __name(browserHeadersHook, "browserHeadersHook");
601
+
602
+ // src/hooks/custom-options.ts
603
+ import "got";
604
+ function customOptionsHook(raw, options) {
605
+ const typedRaw = raw;
606
+ const names = [
607
+ "proxyUrl",
608
+ "headerGeneratorOptions",
609
+ "useHeaderGenerator",
610
+ "insecureHTTPParser",
611
+ "sessionToken"
612
+ ];
613
+ for (const name of names) {
614
+ if (name in raw) {
615
+ options.context[name] = typedRaw[name];
616
+ delete typedRaw[name];
617
+ }
618
+ }
619
+ }
620
+ __name(customOptionsHook, "customOptionsHook");
621
+
622
+ // src/hooks/fix-decompress.ts
623
+ import zlib from "node:zlib";
624
+ import "node:http";
625
+ import { PassThrough } from "node:stream";
626
+ import mimicResponse from "mimic-response";
627
+ var onResponse = /* @__PURE__ */ __name((response, propagate) => {
628
+ const encoding = response.headers["content-encoding"]?.toLowerCase();
629
+ const zlibOptions = {
630
+ flush: zlib.constants.Z_SYNC_FLUSH,
631
+ finishFlush: zlib.constants.Z_SYNC_FLUSH
632
+ };
633
+ const useDecompressor = /* @__PURE__ */ __name((decompressor) => {
634
+ delete response.headers["content-encoding"];
635
+ const result = new PassThrough({
636
+ autoDestroy: false,
637
+ destroy(error, callback) {
638
+ response.destroy();
639
+ callback(error);
640
+ }
641
+ });
642
+ decompressor.once("error", (error) => {
643
+ result.destroy(error);
644
+ });
645
+ response.pipe(decompressor).pipe(result);
646
+ propagate(mimicResponse(response, result));
647
+ }, "useDecompressor");
648
+ if (encoding === "gzip" || encoding === "x-gzip") {
649
+ useDecompressor(zlib.createGunzip(zlibOptions));
650
+ } else if (encoding === "deflate" || encoding === "x-deflate") {
651
+ let read = false;
652
+ response.once("data", (chunk) => {
653
+ read = true;
654
+ response.unshift(chunk);
655
+ const decompressor = (chunk[0] & 15) === 8 ? zlib.createInflate() : zlib.createInflateRaw();
656
+ useDecompressor(decompressor);
657
+ });
658
+ response.once("end", () => {
659
+ if (!read) {
660
+ propagate(response);
661
+ }
662
+ });
663
+ } else if (encoding === "br") {
664
+ let read = false;
665
+ response.once("data", (chunk) => {
666
+ read = true;
667
+ response.unshift(chunk);
668
+ const decompressor = zlib.createBrotliDecompress();
669
+ useDecompressor(decompressor);
670
+ });
671
+ response.once("end", () => {
672
+ if (!read) {
673
+ propagate(response);
674
+ }
675
+ });
676
+ } else {
677
+ propagate(response);
678
+ }
679
+ }, "onResponse");
680
+ var fixDecompress = /* @__PURE__ */ __name((options, next) => {
681
+ const result = next(options);
682
+ result.on("request", (request) => {
683
+ const emit = request.emit.bind(request);
684
+ request.emit = (event, ...args) => {
685
+ if (event === "response" && options.decompress) {
686
+ const response = args[0];
687
+ const emitted = request.listenerCount("response") !== 0;
688
+ onResponse(response, (fixedResponse) => {
689
+ emit("response", fixedResponse);
690
+ });
691
+ return emitted;
692
+ }
693
+ return emit(event, ...args);
694
+ };
695
+ });
696
+ return result;
697
+ }, "fixDecompress");
698
+
699
+ // src/hooks/http2.ts
700
+ import "node:url";
701
+ import "got";
702
+ import { auto as auto3 } from "http2-wrapper";
703
+ function http2Hook(options) {
704
+ const { proxyUrl, sessionData } = options.context;
705
+ if (options.http2 && options.url.protocol !== "http:") {
706
+ options.request = (url, requestOptions, callback) => {
707
+ const typedRequestOptions = requestOptions;
708
+ if (proxyUrl) {
709
+ typedRequestOptions.resolveProtocol = createResolveProtocol(
710
+ proxyUrl,
711
+ sessionData,
712
+ Math.min(options?.timeout?.connect ?? 6e4, options?.timeout?.request ?? 6e4)
713
+ );
714
+ }
715
+ return auto3(url, typedRequestOptions, callback);
716
+ };
717
+ } else {
718
+ options.request = void 0;
719
+ }
720
+ }
721
+ __name(http2Hook, "http2Hook");
722
+
723
+ // src/hooks/insecure-parser.ts
724
+ import "got";
725
+ function insecureParserHook(options) {
726
+ if (options.context.insecureHTTPParser !== void 0) {
727
+ options._unixOptions = {
728
+ // @ts-expect-error Private use
729
+ ...options._unixOptions,
730
+ insecureHTTPParser: options.context.insecureHTTPParser
731
+ };
732
+ }
733
+ }
734
+ __name(insecureParserHook, "insecureParserHook");
735
+
736
+ // src/hooks/options-validation.ts
737
+ import ow from "ow";
738
+ var validationSchema = {
739
+ proxyUrl: ow.optional.string.url,
740
+ useHeaderGenerator: ow.optional.boolean,
741
+ headerGeneratorOptions: ow.optional.object,
742
+ insecureHTTPParser: ow.optional.boolean,
743
+ sessionToken: ow.optional.object
744
+ };
745
+ function optionsValidationHandler(options) {
746
+ ow(options, ow.object.partialShape(validationSchema));
747
+ }
748
+ __name(optionsValidationHandler, "optionsValidationHandler");
749
+
750
+ // src/hooks/referer.ts
751
+ import { URL as URL6 } from "node:url";
752
+ var refererHook = /* @__PURE__ */ __name((options, response) => {
753
+ const url = options.url;
754
+ const resUrl = new URL6(response.url);
755
+ const policy = response.headers["referer-policy"] || "strict-origin-when-cross-origin";
756
+ if (policy === "no-referrer") {
757
+ delete options.headers.referer;
758
+ } else if (policy === "no-referrer-when-downgrade") {
759
+ if (resUrl.protocol === "https:" && url.protocol === "http:") {
760
+ delete options.headers.referer;
761
+ } else {
762
+ options.headers.referer = `${resUrl.origin}${resUrl.pathname}${resUrl.search}`;
763
+ }
764
+ } else if (policy === "origin") {
765
+ options.headers.referer = resUrl.origin;
766
+ } else if (policy === "origin-when-cross-origin") {
767
+ if (url.origin === resUrl.origin) {
768
+ options.headers.referer = `${resUrl.origin}${resUrl.pathname}${resUrl.search}`;
769
+ } else {
770
+ options.headers.referer = resUrl.origin;
771
+ }
772
+ } else if (policy === "same-origin") {
773
+ if (url.origin === resUrl.origin) {
774
+ options.headers.referer = `${resUrl.origin}${resUrl.pathname}${resUrl.search}`;
775
+ } else {
776
+ delete options.headers.referer;
777
+ }
778
+ } else if (policy === "strict-origin") {
779
+ if (resUrl.protocol === "https:" && url.protocol === "http:") {
780
+ delete options.headers.referer;
781
+ } else {
782
+ options.headers.referer = resUrl.origin;
783
+ }
784
+ } else if (policy === "strict-origin-when-cross-origin") {
785
+ if (url.origin === resUrl.origin) {
786
+ options.headers.referer = `${resUrl.origin}${resUrl.pathname}${resUrl.search}`;
787
+ } else if (resUrl.protocol === "https:" && url.protocol === "http:") {
788
+ delete options.headers.referer;
789
+ } else {
790
+ options.headers.referer = resUrl.origin;
791
+ }
792
+ } else if (policy === "unsafe-url") {
793
+ options.headers.referer = `${resUrl.origin}${resUrl.pathname}${resUrl.search}`;
794
+ }
795
+ }, "refererHook");
796
+
797
+ // src/hooks/storage.ts
798
+ import "got";
799
+ var _Storage = class _Storage {
800
+ constructor() {
801
+ __publicField(this, "storage");
802
+ this.storage = /* @__PURE__ */ new WeakMap();
803
+ }
804
+ get(token) {
805
+ if (!token) {
806
+ return;
807
+ }
808
+ if (!this.storage.has(token)) {
809
+ this.storage.set(token, {});
810
+ }
811
+ return this.storage.get(token);
812
+ }
813
+ };
814
+ __name(_Storage, "Storage");
815
+ var Storage = _Storage;
816
+ var storage = new Storage();
817
+ var sessionDataHook = /* @__PURE__ */ __name((options) => {
818
+ options.context.sessionData = storage.get(options.context.sessionToken);
819
+ }, "sessionDataHook");
820
+
821
+ // src/hooks/tls.ts
822
+ import "got";
823
+ var supportsFirefoxFully = Number(process.versions.node.split(".")[0]) >= 17;
824
+ var SSL_OP_TLSEXT_PADDING = 1 << 4;
825
+ var SSL_OP_NO_ENCRYPT_THEN_MAC = 1 << 19;
826
+ var ecdhCurve = {
827
+ firefox: (supportsFirefoxFully ? [
828
+ "X25519",
829
+ "prime256v1",
830
+ "secp384r1",
831
+ "secp521r1",
832
+ "ffdhe2048",
833
+ "ffdhe3072"
834
+ ] : [
835
+ "X25519",
836
+ "prime256v1",
837
+ "secp384r1",
838
+ "secp521r1"
839
+ ]).join(":"),
840
+ chrome: [
841
+ "X25519",
842
+ "prime256v1",
843
+ "secp384r1"
844
+ ].join(":"),
845
+ safari: [
846
+ "X25519",
847
+ "prime256v1",
848
+ "secp384r1",
849
+ "secp521r1"
850
+ ].join(":")
851
+ };
852
+ var sigalgs = {
853
+ firefox: [
854
+ "ecdsa_secp256r1_sha256",
855
+ "ecdsa_secp384r1_sha384",
856
+ "ecdsa_secp521r1_sha512",
857
+ "rsa_pss_rsae_sha256",
858
+ "rsa_pss_rsae_sha384",
859
+ "rsa_pss_rsae_sha512",
860
+ "rsa_pkcs1_sha256",
861
+ "rsa_pkcs1_sha384",
862
+ "rsa_pkcs1_sha512",
863
+ "ECDSA+SHA1",
864
+ "rsa_pkcs1_sha1"
865
+ ].join(":"),
866
+ chrome: [
867
+ "ecdsa_secp256r1_sha256",
868
+ "rsa_pss_rsae_sha256",
869
+ "rsa_pkcs1_sha256",
870
+ "ecdsa_secp384r1_sha384",
871
+ "rsa_pss_rsae_sha384",
872
+ "rsa_pkcs1_sha384",
873
+ "rsa_pss_rsae_sha512",
874
+ "rsa_pkcs1_sha512"
875
+ ].join(":"),
876
+ safari: [
877
+ "ecdsa_secp256r1_sha256",
878
+ "rsa_pss_rsae_sha256",
879
+ "rsa_pkcs1_sha256",
880
+ "ecdsa_secp384r1_sha384",
881
+ "ECDSA+SHA1",
882
+ "rsa_pss_rsae_sha384",
883
+ "rsa_pkcs1_sha384",
884
+ "rsa_pss_rsae_sha512",
885
+ "rsa_pkcs1_sha512",
886
+ "RSA+SHA1"
887
+ ].join(":")
888
+ };
889
+ var knownCiphers = {
890
+ chrome: [
891
+ // Chrome v92
892
+ "TLS_AES_128_GCM_SHA256",
893
+ "TLS_AES_256_GCM_SHA384",
894
+ "TLS_CHACHA20_POLY1305_SHA256",
895
+ "ECDHE-ECDSA-AES128-GCM-SHA256",
896
+ "ECDHE-RSA-AES128-GCM-SHA256",
897
+ "ECDHE-ECDSA-AES256-GCM-SHA384",
898
+ "ECDHE-RSA-AES256-GCM-SHA384",
899
+ "ECDHE-ECDSA-CHACHA20-POLY1305",
900
+ "ECDHE-RSA-CHACHA20-POLY1305",
901
+ // Legacy:
902
+ "ECDHE-RSA-AES128-SHA",
903
+ "ECDHE-RSA-AES256-SHA",
904
+ "AES128-GCM-SHA256",
905
+ "AES256-GCM-SHA384",
906
+ "AES128-SHA",
907
+ "AES256-SHA"
908
+ ].join(":"),
909
+ firefox: [
910
+ // Firefox v91
911
+ "TLS_AES_128_GCM_SHA256",
912
+ "TLS_CHACHA20_POLY1305_SHA256",
913
+ "TLS_AES_256_GCM_SHA384",
914
+ "ECDHE-ECDSA-AES128-GCM-SHA256",
915
+ "ECDHE-RSA-AES128-GCM-SHA256",
916
+ "ECDHE-ECDSA-CHACHA20-POLY1305",
917
+ "ECDHE-RSA-CHACHA20-POLY1305",
918
+ "ECDHE-ECDSA-AES256-GCM-SHA384",
919
+ "ECDHE-RSA-AES256-GCM-SHA384",
920
+ // Legacy:
921
+ "ECDHE-ECDSA-AES256-SHA",
922
+ "ECDHE-ECDSA-AES128-SHA",
923
+ "ECDHE-RSA-AES128-SHA",
924
+ "ECDHE-RSA-AES256-SHA",
925
+ "AES128-GCM-SHA256",
926
+ "AES256-GCM-SHA384",
927
+ "AES128-SHA",
928
+ "AES256-SHA",
929
+ "DES-CBC3-SHA"
930
+ ].join(":"),
931
+ safari: [
932
+ // Safari v14
933
+ "TLS_AES_128_GCM_SHA256",
934
+ "TLS_AES_256_GCM_SHA384",
935
+ "TLS_CHACHA20_POLY1305_SHA256",
936
+ "ECDHE-ECDSA-AES256-GCM-SHA384",
937
+ "ECDHE-ECDSA-AES128-GCM-SHA256",
938
+ "ECDHE-ECDSA-CHACHA20-POLY1305",
939
+ "ECDHE-RSA-AES256-GCM-SHA384",
940
+ "ECDHE-RSA-AES128-GCM-SHA256",
941
+ "ECDHE-RSA-CHACHA20-POLY1305",
942
+ // Legacy:
943
+ "ECDHE-ECDSA-AES256-SHA384",
944
+ "ECDHE-ECDSA-AES128-SHA256",
945
+ "ECDHE-ECDSA-AES256-SHA",
946
+ "ECDHE-ECDSA-AES128-SHA",
947
+ "ECDHE-RSA-AES256-SHA384",
948
+ "ECDHE-RSA-AES128-SHA256",
949
+ "ECDHE-RSA-AES256-SHA",
950
+ "ECDHE-RSA-AES128-SHA",
951
+ "AES256-GCM-SHA384",
952
+ "AES128-GCM-SHA256",
953
+ "AES256-SHA256",
954
+ "AES128-SHA256",
955
+ "AES256-SHA",
956
+ "AES128-SHA",
957
+ "ECDHE-ECDSA-DES-CBC3-SHA",
958
+ "ECDHE-RSA-DES-CBC3-SHA",
959
+ "DES-CBC3-SHA"
960
+ ].join(":")
961
+ };
962
+ var minVersion = {
963
+ firefox: "TLSv1.2",
964
+ chrome: "TLSv1",
965
+ safari: "TLSv1.2"
966
+ };
967
+ var maxVersion = {
968
+ firefox: "TLSv1.3",
969
+ chrome: "TLSv1.3",
970
+ safari: "TLSv1.3"
971
+ };
972
+ var secureOptions = {
973
+ firefox: SSL_OP_TLSEXT_PADDING | SSL_OP_NO_ENCRYPT_THEN_MAC,
974
+ chrome: SSL_OP_TLSEXT_PADDING | SSL_OP_NO_ENCRYPT_THEN_MAC,
975
+ safari: SSL_OP_TLSEXT_PADDING | SSL_OP_NO_ENCRYPT_THEN_MAC
976
+ };
977
+ var requestOCSP = {
978
+ firefox: true,
979
+ chrome: true,
980
+ safari: true
981
+ };
982
+ var getUserAgent = /* @__PURE__ */ __name((headers) => {
983
+ for (const [header, value] of Object.entries(headers)) {
984
+ if (header.toLowerCase() === "user-agent") {
985
+ return value;
986
+ }
987
+ }
988
+ return void 0;
989
+ }, "getUserAgent");
990
+ var getBrowser = /* @__PURE__ */ __name((userAgent) => {
991
+ if (!userAgent) {
992
+ return;
993
+ }
994
+ let browser;
995
+ if (userAgent.includes("Firefox")) {
996
+ browser = "firefox";
997
+ } else if (userAgent.includes("Chrome")) {
998
+ browser = "chrome";
999
+ } else {
1000
+ browser = "safari";
1001
+ }
1002
+ return browser;
1003
+ }, "getBrowser");
1004
+ function tlsHook(options) {
1005
+ const { https: https3 } = options;
1006
+ if (https3.ciphers || https3.signatureAlgorithms || https3.minVersion || https3.maxVersion) {
1007
+ return;
1008
+ }
1009
+ const browser = getBrowser(getUserAgent(options.headers)) ?? "firefox";
1010
+ https3.ciphers = knownCiphers[browser];
1011
+ https3.signatureAlgorithms = sigalgs[browser];
1012
+ https3.ecdhCurve = ecdhCurve[browser];
1013
+ https3.minVersion = minVersion[browser];
1014
+ https3.maxVersion = maxVersion[browser];
1015
+ options._unixOptions = {
1016
+ // @ts-expect-error Private use
1017
+ ...options._unixOptions,
1018
+ secureOptions: secureOptions[browser],
1019
+ requestOCSP: requestOCSP[browser]
1020
+ };
1021
+ }
1022
+ __name(tlsHook, "tlsHook");
1023
+
1024
+ // src/index.ts
1025
+ export * from "got";
1026
+ var handlers = [
1027
+ fixDecompress
1028
+ ];
1029
+ var beforeRequest = [
1030
+ insecureParserHook,
1031
+ sessionDataHook,
1032
+ http2Hook,
1033
+ proxyHook,
1034
+ browserHeadersHook,
1035
+ tlsHook
1036
+ ];
1037
+ var init = [
1038
+ optionsValidationHandler,
1039
+ customOptionsHook
1040
+ ];
1041
+ var beforeRedirect = [
1042
+ refererHook
1043
+ ];
1044
+ function createGotScrapingOptions() {
1045
+ return {
1046
+ handlers,
1047
+ mutableDefaults: true,
1048
+ // Most of the new browsers use HTTP/2
1049
+ http2: true,
1050
+ https: {
1051
+ // In contrast to browsers, we don't usually do login operations.
1052
+ // We want the content.
1053
+ rejectUnauthorized: false
1054
+ },
1055
+ // Don't fail on 404
1056
+ throwHttpErrors: false,
1057
+ timeout: { request: 6e4 },
1058
+ retry: { limit: 0 },
1059
+ headers: {
1060
+ "user-agent": void 0
1061
+ },
1062
+ context: {
1063
+ headerGenerator: new HeaderGenerator2(),
1064
+ useHeaderGenerator: true,
1065
+ insecureHTTPParser: true
1066
+ },
1067
+ agent: {
1068
+ http: new TransformHeadersAgent(http3.globalAgent),
1069
+ https: new TransformHeadersAgent(https2.globalAgent)
1070
+ },
1071
+ hooks: {
1072
+ init,
1073
+ beforeRequest,
1074
+ beforeRedirect
1075
+ }
1076
+ };
1077
+ }
1078
+ __name(createGotScrapingOptions, "createGotScrapingOptions");
1079
+ var gotScraping = originalGot.extend(createGotScrapingOptions());
1080
+ var setupDecodeURI = /* @__PURE__ */ __name(() => {
1081
+ const { set } = Object.getOwnPropertyDescriptor(Options8.prototype, "url");
1082
+ Object.defineProperty(Options8.prototype, "url", {
1083
+ set(value) {
1084
+ const originalDecodeURI = global.decodeURI;
1085
+ global.decodeURI = (str) => str;
1086
+ try {
1087
+ return set.call(this, value);
1088
+ } finally {
1089
+ global.decodeURI = originalDecodeURI;
1090
+ }
1091
+ }
1092
+ });
1093
+ }, "setupDecodeURI");
1094
+ setupDecodeURI();
1095
+ var hooks = {
1096
+ init,
1097
+ beforeRequest,
1098
+ beforeRedirect,
1099
+ fixDecompress,
1100
+ insecureParserHook,
1101
+ sessionDataHook,
1102
+ http2Hook,
1103
+ proxyHook,
1104
+ browserHeadersHook,
1105
+ tlsHook,
1106
+ optionsValidationHandler,
1107
+ customOptionsHook,
1108
+ refererHook
1109
+ };
1110
+ export {
1111
+ TransformHeadersAgent,
1112
+ createGotScrapingOptions,
1113
+ getAgents,
1114
+ gotScraping,
1115
+ hooks
1116
+ };
1117
+ //# sourceMappingURL=index.js.map