@kikobeats/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,1114 @@
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 http2Wrapper 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 http2 = http2Wrapper;
354
+ var { auto } = http2Wrapper;
355
+ var {
356
+ HttpOverHttp2,
357
+ HttpsOverHttp2,
358
+ Http2OverHttp2,
359
+ Http2OverHttps,
360
+ Http2OverHttp
361
+ } = http2.proxies;
362
+ async function proxyHook(options) {
363
+ const { context: { proxyUrl } } = options;
364
+ if (proxyUrl) {
365
+ const parsedProxy = new URL2(proxyUrl);
366
+ validateProxyProtocol(parsedProxy.protocol);
367
+ options.agent = await getAgents(parsedProxy, options.https.rejectUnauthorized);
368
+ }
369
+ }
370
+ __name(proxyHook, "proxyHook");
371
+ var _ProxyError = class _ProxyError extends Error {
372
+ };
373
+ __name(_ProxyError, "ProxyError");
374
+ var ProxyError = _ProxyError;
375
+ function validateProxyProtocol(protocol) {
376
+ const isSupported = protocol === "http:" || protocol === "https:";
377
+ if (!isSupported) {
378
+ throw new ProxyError(`Proxy URL protocol "${protocol}" is not supported. Please use HTTP or HTTPS.`);
379
+ }
380
+ }
381
+ __name(validateProxyProtocol, "validateProxyProtocol");
382
+ async function getAgents(parsedProxyUrl, rejectUnauthorized) {
383
+ const headers = {};
384
+ const basic = buildBasicAuthHeader(parsedProxyUrl);
385
+ if (basic) {
386
+ headers.authorization = basic;
387
+ headers["proxy-authorization"] = basic;
388
+ }
389
+ const wrapperOptions = {
390
+ proxyOptions: {
391
+ url: parsedProxyUrl,
392
+ headers,
393
+ // Based on the got https.rejectUnauthorized option
394
+ rejectUnauthorized
395
+ },
396
+ // The sockets won't be reused, no need to keep them
397
+ maxFreeSockets: 0,
398
+ maxEmptySessions: 0
399
+ };
400
+ const nativeOptions = {
401
+ proxy: parsedProxyUrl,
402
+ // The sockets won't be reused, no need to keep them
403
+ maxFreeSockets: 0
404
+ };
405
+ let agent;
406
+ if (parsedProxyUrl.protocol === "https:") {
407
+ let alpnProtocol = "http/1.1";
408
+ try {
409
+ const result = await auto.resolveProtocol({
410
+ host: parsedProxyUrl.hostname,
411
+ port: parsedProxyUrl.port,
412
+ rejectUnauthorized,
413
+ ALPNProtocols: ["h2", "http/1.1"],
414
+ servername: parsedProxyUrl.hostname
415
+ });
416
+ alpnProtocol = result.alpnProtocol;
417
+ } catch {
418
+ }
419
+ const proxyIsHttp2 = alpnProtocol === "h2";
420
+ if (proxyIsHttp2) {
421
+ agent = {
422
+ http: new TransformHeadersAgent(new HttpOverHttp2(wrapperOptions)),
423
+ https: new TransformHeadersAgent(new HttpsOverHttp2(wrapperOptions)),
424
+ http2: new Http2OverHttp2(wrapperOptions)
425
+ };
426
+ } else {
427
+ agent = {
428
+ // @ts-expect-error New @types/node patch has narrower types than the originally exported got-scraping interface
429
+ http: new TransformHeadersAgent(new HttpProxyAgent(nativeOptions)),
430
+ // @ts-expect-error New @types/node patch has narrower types than the originally exported got-scraping interface
431
+ https: new TransformHeadersAgent(new HttpsProxyAgent(nativeOptions)),
432
+ http2: new Http2OverHttps(wrapperOptions)
433
+ };
434
+ }
435
+ } else {
436
+ agent = {
437
+ http: new TransformHeadersAgent(new HttpRegularProxyAgent(nativeOptions)),
438
+ // @ts-expect-error New @types/node patch has narrower types than the originally exported got-scraping interface
439
+ https: new TransformHeadersAgent(new HttpsProxyAgent(nativeOptions)),
440
+ http2: new Http2OverHttp(wrapperOptions)
441
+ };
442
+ }
443
+ return agent;
444
+ }
445
+ __name(getAgents, "getAgents");
446
+
447
+ // src/resolve-protocol.ts
448
+ var connect = /* @__PURE__ */ __name(async (proxyUrl, options, callback) => new Promise((resolve, reject) => {
449
+ let host = `${options.host}:${options.port}`;
450
+ if (isIPv62(options.host)) {
451
+ host = `[${options.host}]:${options.port}`;
452
+ }
453
+ void (async () => {
454
+ try {
455
+ const headers = {
456
+ host
457
+ };
458
+ const url = new URL3(proxyUrl);
459
+ const basic = buildBasicAuthHeader(url);
460
+ if (basic) {
461
+ headers.authorization = basic;
462
+ headers["proxy-authorization"] = basic;
463
+ }
464
+ const request = await auto2(url, {
465
+ method: "CONNECT",
466
+ headers,
467
+ path: host,
468
+ // TODO: this property doesn't exist according to the types
469
+ pathname: host,
470
+ rejectUnauthorized: false
471
+ });
472
+ request.end();
473
+ request.once("error", reject);
474
+ request.once("connect", (response, socket, head) => {
475
+ if (response.statusCode !== 200 || head.length > 0) {
476
+ reject(new ProxyError(`Proxy responded with ${response.statusCode} ${response.statusMessage}: ${head.length} bytes.
477
+
478
+ Below is the first 100 bytes of the proxy response body:
479
+ ${head.toString("utf8", 0, 100)}`, { cause: head.toString("utf8") }));
480
+ socket.destroy();
481
+ return;
482
+ }
483
+ const tlsSocket = tls2.connect({
484
+ ...options,
485
+ socket
486
+ }, callback);
487
+ resolve(tlsSocket);
488
+ });
489
+ } catch (error) {
490
+ reject(error);
491
+ }
492
+ })();
493
+ }), "connect");
494
+ var createCaches = /* @__PURE__ */ __name(() => ({
495
+ protocolCache: new QuickLRU({ maxSize: 1e3 }),
496
+ resolveAlpnQueue: /* @__PURE__ */ new Map()
497
+ }), "createCaches");
498
+ var defaults = createCaches();
499
+ var createResolveProtocol = /* @__PURE__ */ __name((proxyUrl, sessionData, timeout) => {
500
+ let { protocolCache, resolveAlpnQueue } = defaults;
501
+ if (sessionData) {
502
+ if (!sessionData.protocolCache || !sessionData.resolveAlpnQueue) {
503
+ Object.assign(sessionData, createCaches());
504
+ }
505
+ protocolCache = sessionData.protocolCache;
506
+ resolveAlpnQueue = sessionData.resolveAlpnQueue;
507
+ }
508
+ const connectWithProxy = /* @__PURE__ */ __name(async (pOptions, pCallback) => {
509
+ return connect(proxyUrl, pOptions, pCallback);
510
+ }, "connectWithProxy");
511
+ const resolveProtocol = auto2.createResolveProtocol(
512
+ protocolCache,
513
+ resolveAlpnQueue,
514
+ connectWithProxy
515
+ );
516
+ return async (...args) => resolveProtocol({
517
+ ...args[0],
518
+ timeout
519
+ });
520
+ }, "createResolveProtocol");
521
+
522
+ // src/hooks/browser-headers.ts
523
+ function mergeHeaders(original, overrides) {
524
+ const fixedHeaders = /* @__PURE__ */ new Map();
525
+ for (const entry of Object.entries(original)) {
526
+ fixedHeaders.set(entry[0].toLowerCase(), entry);
527
+ }
528
+ for (const entry of Object.entries(overrides)) {
529
+ fixedHeaders.set(entry[0].toLowerCase(), entry);
530
+ }
531
+ return Object.fromEntries(fixedHeaders.values());
532
+ }
533
+ __name(mergeHeaders, "mergeHeaders");
534
+ var getResolveProtocolFunction = /* @__PURE__ */ __name((options, proxyUrl, sessionData) => {
535
+ const { resolveProtocol } = options;
536
+ if (resolveProtocol) {
537
+ return resolveProtocol;
538
+ }
539
+ if (proxyUrl) {
540
+ return createResolveProtocol(proxyUrl, sessionData, Math.min(options?.timeout?.connect ?? 6e4, options?.timeout?.request ?? 6e4));
541
+ }
542
+ return (...args) => http22.auto.resolveProtocol({
543
+ ...args[0],
544
+ timeout: Math.min(options?.timeout?.connect ?? 6e4, options?.timeout?.request ?? 6e4)
545
+ });
546
+ }, "getResolveProtocolFunction");
547
+ async function browserHeadersHook(options) {
548
+ const { context } = options;
549
+ const {
550
+ headerGeneratorOptions,
551
+ useHeaderGenerator,
552
+ headerGenerator,
553
+ proxyUrl
554
+ } = context;
555
+ const sessionData = context.sessionData;
556
+ if (!useHeaderGenerator || !headerGenerator)
557
+ return;
558
+ const createHeadersPair = /* @__PURE__ */ __name(() => ({
559
+ 1: headerGenerator.getHeaders({
560
+ httpVersion: "1",
561
+ ...headerGeneratorOptions
562
+ }),
563
+ 2: headerGenerator.getHeaders({
564
+ httpVersion: "2",
565
+ ...headerGeneratorOptions
566
+ })
567
+ }), "createHeadersPair");
568
+ const url = options.url;
569
+ const resolveProtocol = getResolveProtocolFunction(options, proxyUrl, sessionData);
570
+ let alpnProtocol;
571
+ if (url.protocol === "https:") {
572
+ alpnProtocol = (await resolveProtocol({
573
+ host: url.hostname,
574
+ port: url.port || 443,
575
+ rejectUnauthorized: false,
576
+ ALPNProtocols: ["h2", "http/1.1"],
577
+ servername: url.hostname
578
+ })).alpnProtocol;
579
+ }
580
+ const httpVersion = alpnProtocol === "h2" ? "2" : "1";
581
+ let generatedHeaders;
582
+ if (sessionData) {
583
+ if (!sessionData.headers) {
584
+ sessionData.headers = createHeadersPair();
585
+ }
586
+ generatedHeaders = sessionData.headers[httpVersion];
587
+ } else {
588
+ generatedHeaders = headerGenerator.getHeaders({
589
+ httpVersion,
590
+ ...headerGeneratorOptions
591
+ });
592
+ }
593
+ if (!options.decompress) {
594
+ for (const key of Object.keys(generatedHeaders)) {
595
+ if (key.toLowerCase() === "accept-encoding") {
596
+ delete generatedHeaders[key];
597
+ }
598
+ }
599
+ }
600
+ options.headers = mergeHeaders(generatedHeaders, options.headers);
601
+ }
602
+ __name(browserHeadersHook, "browserHeadersHook");
603
+
604
+ // src/hooks/custom-options.ts
605
+ import "got";
606
+ function customOptionsHook(raw, options) {
607
+ const typedRaw = raw;
608
+ const names = [
609
+ "proxyUrl",
610
+ "headerGeneratorOptions",
611
+ "useHeaderGenerator",
612
+ "insecureHTTPParser",
613
+ "sessionToken"
614
+ ];
615
+ for (const name of names) {
616
+ if (name in raw) {
617
+ options.context[name] = typedRaw[name];
618
+ delete typedRaw[name];
619
+ }
620
+ }
621
+ }
622
+ __name(customOptionsHook, "customOptionsHook");
623
+
624
+ // src/hooks/fix-decompress.ts
625
+ import zlib from "node:zlib";
626
+ import "node:http";
627
+ import { PassThrough } from "node:stream";
628
+ import mimicResponse from "mimic-response";
629
+ var onResponse = /* @__PURE__ */ __name((response, propagate) => {
630
+ const encoding = response.headers["content-encoding"]?.toLowerCase();
631
+ const zlibOptions = {
632
+ flush: zlib.constants.Z_SYNC_FLUSH,
633
+ finishFlush: zlib.constants.Z_SYNC_FLUSH
634
+ };
635
+ const useDecompressor = /* @__PURE__ */ __name((decompressor) => {
636
+ delete response.headers["content-encoding"];
637
+ const result = new PassThrough({
638
+ autoDestroy: false,
639
+ destroy(error, callback) {
640
+ response.destroy();
641
+ callback(error);
642
+ }
643
+ });
644
+ decompressor.once("error", (error) => {
645
+ result.destroy(error);
646
+ });
647
+ response.pipe(decompressor).pipe(result);
648
+ propagate(mimicResponse(response, result));
649
+ }, "useDecompressor");
650
+ if (encoding === "gzip" || encoding === "x-gzip") {
651
+ useDecompressor(zlib.createGunzip(zlibOptions));
652
+ } else if (encoding === "deflate" || encoding === "x-deflate") {
653
+ let read = false;
654
+ response.once("data", (chunk) => {
655
+ read = true;
656
+ response.unshift(chunk);
657
+ const decompressor = (chunk[0] & 15) === 8 ? zlib.createInflate() : zlib.createInflateRaw();
658
+ useDecompressor(decompressor);
659
+ });
660
+ response.once("end", () => {
661
+ if (!read) {
662
+ propagate(response);
663
+ }
664
+ });
665
+ } else if (encoding === "br") {
666
+ let read = false;
667
+ response.once("data", (chunk) => {
668
+ read = true;
669
+ response.unshift(chunk);
670
+ const decompressor = zlib.createBrotliDecompress();
671
+ useDecompressor(decompressor);
672
+ });
673
+ response.once("end", () => {
674
+ if (!read) {
675
+ propagate(response);
676
+ }
677
+ });
678
+ } else {
679
+ propagate(response);
680
+ }
681
+ }, "onResponse");
682
+ var fixDecompress = /* @__PURE__ */ __name((options, next) => {
683
+ const result = next(options);
684
+ result.on("request", (request) => {
685
+ const emit = request.emit.bind(request);
686
+ request.emit = (event, ...args) => {
687
+ if (event === "response" && options.decompress) {
688
+ const response = args[0];
689
+ const emitted = request.listenerCount("response") !== 0;
690
+ onResponse(response, (fixedResponse) => {
691
+ emit("response", fixedResponse);
692
+ });
693
+ return emitted;
694
+ }
695
+ return emit(event, ...args);
696
+ };
697
+ });
698
+ return result;
699
+ }, "fixDecompress");
700
+
701
+ // src/hooks/http2.ts
702
+ import "node:url";
703
+ import "got";
704
+ import { auto as auto3 } from "http2-wrapper";
705
+ function http2Hook(options) {
706
+ const { proxyUrl, sessionData } = options.context;
707
+ if (options.http2 && options.url.protocol !== "http:") {
708
+ options.request = (url, requestOptions, callback) => {
709
+ const typedRequestOptions = requestOptions;
710
+ if (proxyUrl) {
711
+ typedRequestOptions.resolveProtocol = createResolveProtocol(
712
+ proxyUrl,
713
+ sessionData,
714
+ Math.min(options?.timeout?.connect ?? 6e4, options?.timeout?.request ?? 6e4)
715
+ );
716
+ }
717
+ return auto3(url, typedRequestOptions, callback);
718
+ };
719
+ } else {
720
+ options.request = void 0;
721
+ }
722
+ }
723
+ __name(http2Hook, "http2Hook");
724
+
725
+ // src/hooks/insecure-parser.ts
726
+ import "got";
727
+ function insecureParserHook(options) {
728
+ if (options.context.insecureHTTPParser !== void 0) {
729
+ options._unixOptions = {
730
+ // @ts-expect-error Private use
731
+ ...options._unixOptions,
732
+ insecureHTTPParser: options.context.insecureHTTPParser
733
+ };
734
+ }
735
+ }
736
+ __name(insecureParserHook, "insecureParserHook");
737
+
738
+ // src/hooks/options-validation.ts
739
+ import ow from "ow";
740
+ var validationSchema = {
741
+ proxyUrl: ow.optional.string.url,
742
+ useHeaderGenerator: ow.optional.boolean,
743
+ headerGeneratorOptions: ow.optional.object,
744
+ insecureHTTPParser: ow.optional.boolean,
745
+ sessionToken: ow.optional.object
746
+ };
747
+ function optionsValidationHandler(options) {
748
+ ow(options, ow.object.partialShape(validationSchema));
749
+ }
750
+ __name(optionsValidationHandler, "optionsValidationHandler");
751
+
752
+ // src/hooks/referer.ts
753
+ import { URL as URL6 } from "node:url";
754
+ var refererHook = /* @__PURE__ */ __name((options, response) => {
755
+ const url = options.url;
756
+ const resUrl = new URL6(response.url);
757
+ const policy = response.headers["referer-policy"] || "strict-origin-when-cross-origin";
758
+ if (policy === "no-referrer") {
759
+ delete options.headers.referer;
760
+ } else if (policy === "no-referrer-when-downgrade") {
761
+ if (resUrl.protocol === "https:" && url.protocol === "http:") {
762
+ delete options.headers.referer;
763
+ } else {
764
+ options.headers.referer = `${resUrl.origin}${resUrl.pathname}${resUrl.search}`;
765
+ }
766
+ } else if (policy === "origin") {
767
+ options.headers.referer = resUrl.origin;
768
+ } else if (policy === "origin-when-cross-origin") {
769
+ if (url.origin === resUrl.origin) {
770
+ options.headers.referer = `${resUrl.origin}${resUrl.pathname}${resUrl.search}`;
771
+ } else {
772
+ options.headers.referer = resUrl.origin;
773
+ }
774
+ } else if (policy === "same-origin") {
775
+ if (url.origin === resUrl.origin) {
776
+ options.headers.referer = `${resUrl.origin}${resUrl.pathname}${resUrl.search}`;
777
+ } else {
778
+ delete options.headers.referer;
779
+ }
780
+ } else if (policy === "strict-origin") {
781
+ if (resUrl.protocol === "https:" && url.protocol === "http:") {
782
+ delete options.headers.referer;
783
+ } else {
784
+ options.headers.referer = resUrl.origin;
785
+ }
786
+ } else if (policy === "strict-origin-when-cross-origin") {
787
+ if (url.origin === resUrl.origin) {
788
+ options.headers.referer = `${resUrl.origin}${resUrl.pathname}${resUrl.search}`;
789
+ } else if (resUrl.protocol === "https:" && url.protocol === "http:") {
790
+ delete options.headers.referer;
791
+ } else {
792
+ options.headers.referer = resUrl.origin;
793
+ }
794
+ } else if (policy === "unsafe-url") {
795
+ options.headers.referer = `${resUrl.origin}${resUrl.pathname}${resUrl.search}`;
796
+ }
797
+ }, "refererHook");
798
+
799
+ // src/hooks/storage.ts
800
+ import "got";
801
+ var _Storage = class _Storage {
802
+ constructor() {
803
+ __publicField(this, "storage");
804
+ this.storage = /* @__PURE__ */ new WeakMap();
805
+ }
806
+ get(token) {
807
+ if (!token) {
808
+ return;
809
+ }
810
+ if (!this.storage.has(token)) {
811
+ this.storage.set(token, {});
812
+ }
813
+ return this.storage.get(token);
814
+ }
815
+ };
816
+ __name(_Storage, "Storage");
817
+ var Storage = _Storage;
818
+ var storage = new Storage();
819
+ var sessionDataHook = /* @__PURE__ */ __name((options) => {
820
+ options.context.sessionData = storage.get(options.context.sessionToken);
821
+ }, "sessionDataHook");
822
+
823
+ // src/hooks/tls.ts
824
+ import "got";
825
+ var supportsFirefoxFully = Number(process.versions.node.split(".")[0]) >= 17;
826
+ var SSL_OP_TLSEXT_PADDING = 1 << 4;
827
+ var SSL_OP_NO_ENCRYPT_THEN_MAC = 1 << 19;
828
+ var ecdhCurve = {
829
+ firefox: (supportsFirefoxFully ? [
830
+ "X25519",
831
+ "prime256v1",
832
+ "secp384r1",
833
+ "secp521r1",
834
+ "ffdhe2048",
835
+ "ffdhe3072"
836
+ ] : [
837
+ "X25519",
838
+ "prime256v1",
839
+ "secp384r1",
840
+ "secp521r1"
841
+ ]).join(":"),
842
+ chrome: [
843
+ "X25519",
844
+ "prime256v1",
845
+ "secp384r1"
846
+ ].join(":"),
847
+ safari: [
848
+ "X25519",
849
+ "prime256v1",
850
+ "secp384r1",
851
+ "secp521r1"
852
+ ].join(":")
853
+ };
854
+ var sigalgs = {
855
+ firefox: [
856
+ "ecdsa_secp256r1_sha256",
857
+ "ecdsa_secp384r1_sha384",
858
+ "ecdsa_secp521r1_sha512",
859
+ "rsa_pss_rsae_sha256",
860
+ "rsa_pss_rsae_sha384",
861
+ "rsa_pss_rsae_sha512",
862
+ "rsa_pkcs1_sha256",
863
+ "rsa_pkcs1_sha384",
864
+ "rsa_pkcs1_sha512",
865
+ "ECDSA+SHA1",
866
+ "rsa_pkcs1_sha1"
867
+ ].join(":"),
868
+ chrome: [
869
+ "ecdsa_secp256r1_sha256",
870
+ "rsa_pss_rsae_sha256",
871
+ "rsa_pkcs1_sha256",
872
+ "ecdsa_secp384r1_sha384",
873
+ "rsa_pss_rsae_sha384",
874
+ "rsa_pkcs1_sha384",
875
+ "rsa_pss_rsae_sha512",
876
+ "rsa_pkcs1_sha512"
877
+ ].join(":"),
878
+ safari: [
879
+ "ecdsa_secp256r1_sha256",
880
+ "rsa_pss_rsae_sha256",
881
+ "rsa_pkcs1_sha256",
882
+ "ecdsa_secp384r1_sha384",
883
+ "ECDSA+SHA1",
884
+ "rsa_pss_rsae_sha384",
885
+ "rsa_pkcs1_sha384",
886
+ "rsa_pss_rsae_sha512",
887
+ "rsa_pkcs1_sha512",
888
+ "RSA+SHA1"
889
+ ].join(":")
890
+ };
891
+ var knownCiphers = {
892
+ chrome: [
893
+ // Chrome v92
894
+ "TLS_AES_128_GCM_SHA256",
895
+ "TLS_AES_256_GCM_SHA384",
896
+ "TLS_CHACHA20_POLY1305_SHA256",
897
+ "ECDHE-ECDSA-AES128-GCM-SHA256",
898
+ "ECDHE-RSA-AES128-GCM-SHA256",
899
+ "ECDHE-ECDSA-AES256-GCM-SHA384",
900
+ "ECDHE-RSA-AES256-GCM-SHA384",
901
+ "ECDHE-ECDSA-CHACHA20-POLY1305",
902
+ "ECDHE-RSA-CHACHA20-POLY1305",
903
+ // Legacy:
904
+ "ECDHE-RSA-AES128-SHA",
905
+ "ECDHE-RSA-AES256-SHA",
906
+ "AES128-GCM-SHA256",
907
+ "AES256-GCM-SHA384",
908
+ "AES128-SHA",
909
+ "AES256-SHA"
910
+ ].join(":"),
911
+ firefox: [
912
+ // Firefox v91
913
+ "TLS_AES_128_GCM_SHA256",
914
+ "TLS_CHACHA20_POLY1305_SHA256",
915
+ "TLS_AES_256_GCM_SHA384",
916
+ "ECDHE-ECDSA-AES128-GCM-SHA256",
917
+ "ECDHE-RSA-AES128-GCM-SHA256",
918
+ "ECDHE-ECDSA-CHACHA20-POLY1305",
919
+ "ECDHE-RSA-CHACHA20-POLY1305",
920
+ "ECDHE-ECDSA-AES256-GCM-SHA384",
921
+ "ECDHE-RSA-AES256-GCM-SHA384",
922
+ // Legacy:
923
+ "ECDHE-ECDSA-AES256-SHA",
924
+ "ECDHE-ECDSA-AES128-SHA",
925
+ "ECDHE-RSA-AES128-SHA",
926
+ "ECDHE-RSA-AES256-SHA",
927
+ "AES128-GCM-SHA256",
928
+ "AES256-GCM-SHA384",
929
+ "AES128-SHA",
930
+ "AES256-SHA",
931
+ "DES-CBC3-SHA"
932
+ ].join(":"),
933
+ safari: [
934
+ // Safari v14
935
+ "TLS_AES_128_GCM_SHA256",
936
+ "TLS_AES_256_GCM_SHA384",
937
+ "TLS_CHACHA20_POLY1305_SHA256",
938
+ "ECDHE-ECDSA-AES256-GCM-SHA384",
939
+ "ECDHE-ECDSA-AES128-GCM-SHA256",
940
+ "ECDHE-ECDSA-CHACHA20-POLY1305",
941
+ "ECDHE-RSA-AES256-GCM-SHA384",
942
+ "ECDHE-RSA-AES128-GCM-SHA256",
943
+ "ECDHE-RSA-CHACHA20-POLY1305",
944
+ // Legacy:
945
+ "ECDHE-ECDSA-AES256-SHA384",
946
+ "ECDHE-ECDSA-AES128-SHA256",
947
+ "ECDHE-ECDSA-AES256-SHA",
948
+ "ECDHE-ECDSA-AES128-SHA",
949
+ "ECDHE-RSA-AES256-SHA384",
950
+ "ECDHE-RSA-AES128-SHA256",
951
+ "ECDHE-RSA-AES256-SHA",
952
+ "ECDHE-RSA-AES128-SHA",
953
+ "AES256-GCM-SHA384",
954
+ "AES128-GCM-SHA256",
955
+ "AES256-SHA256",
956
+ "AES128-SHA256",
957
+ "AES256-SHA",
958
+ "AES128-SHA",
959
+ "ECDHE-ECDSA-DES-CBC3-SHA",
960
+ "ECDHE-RSA-DES-CBC3-SHA",
961
+ "DES-CBC3-SHA"
962
+ ].join(":")
963
+ };
964
+ var minVersion = {
965
+ firefox: "TLSv1.2",
966
+ chrome: "TLSv1",
967
+ safari: "TLSv1.2"
968
+ };
969
+ var maxVersion = {
970
+ firefox: "TLSv1.3",
971
+ chrome: "TLSv1.3",
972
+ safari: "TLSv1.3"
973
+ };
974
+ var secureOptions = {
975
+ firefox: SSL_OP_TLSEXT_PADDING | SSL_OP_NO_ENCRYPT_THEN_MAC,
976
+ chrome: SSL_OP_TLSEXT_PADDING | SSL_OP_NO_ENCRYPT_THEN_MAC,
977
+ safari: SSL_OP_TLSEXT_PADDING | SSL_OP_NO_ENCRYPT_THEN_MAC
978
+ };
979
+ var requestOCSP = {
980
+ firefox: true,
981
+ chrome: true,
982
+ safari: true
983
+ };
984
+ var getUserAgent = /* @__PURE__ */ __name((headers) => {
985
+ for (const [header, value] of Object.entries(headers)) {
986
+ if (header.toLowerCase() === "user-agent") {
987
+ return value;
988
+ }
989
+ }
990
+ return void 0;
991
+ }, "getUserAgent");
992
+ var getBrowser = /* @__PURE__ */ __name((userAgent) => {
993
+ if (!userAgent) {
994
+ return;
995
+ }
996
+ let browser;
997
+ if (userAgent.includes("Firefox")) {
998
+ browser = "firefox";
999
+ } else if (userAgent.includes("Chrome")) {
1000
+ browser = "chrome";
1001
+ } else {
1002
+ browser = "safari";
1003
+ }
1004
+ return browser;
1005
+ }, "getBrowser");
1006
+ function tlsHook(options) {
1007
+ const { https: https3 } = options;
1008
+ if (https3.ciphers || https3.signatureAlgorithms || https3.minVersion || https3.maxVersion) {
1009
+ return;
1010
+ }
1011
+ const browser = getBrowser(getUserAgent(options.headers)) ?? "firefox";
1012
+ https3.ciphers = knownCiphers[browser];
1013
+ https3.signatureAlgorithms = sigalgs[browser];
1014
+ https3.ecdhCurve = ecdhCurve[browser];
1015
+ https3.minVersion = minVersion[browser];
1016
+ https3.maxVersion = maxVersion[browser];
1017
+ options._unixOptions = {
1018
+ // @ts-expect-error Private use
1019
+ ...options._unixOptions,
1020
+ secureOptions: secureOptions[browser],
1021
+ requestOCSP: requestOCSP[browser]
1022
+ };
1023
+ }
1024
+ __name(tlsHook, "tlsHook");
1025
+
1026
+ // src/index.ts
1027
+ export * from "got";
1028
+ var handlers = [
1029
+ fixDecompress
1030
+ ];
1031
+ var beforeRequest = [
1032
+ insecureParserHook,
1033
+ sessionDataHook,
1034
+ http2Hook,
1035
+ proxyHook,
1036
+ browserHeadersHook,
1037
+ tlsHook
1038
+ ];
1039
+ var init = [
1040
+ optionsValidationHandler,
1041
+ customOptionsHook
1042
+ ];
1043
+ var beforeRedirect = [
1044
+ refererHook
1045
+ ];
1046
+ var gotScraping = originalGot.extend({
1047
+ handlers,
1048
+ mutableDefaults: true,
1049
+ // Most of the new browsers use HTTP/2
1050
+ http2: true,
1051
+ https: {
1052
+ // In contrast to browsers, we don't usually do login operations.
1053
+ // We want the content.
1054
+ rejectUnauthorized: false
1055
+ },
1056
+ // Don't fail on 404
1057
+ throwHttpErrors: false,
1058
+ timeout: { request: 6e4 },
1059
+ retry: { limit: 0 },
1060
+ headers: {
1061
+ "user-agent": void 0
1062
+ },
1063
+ context: {
1064
+ headerGenerator: new HeaderGenerator2(),
1065
+ useHeaderGenerator: true,
1066
+ insecureHTTPParser: true
1067
+ },
1068
+ agent: {
1069
+ http: new TransformHeadersAgent(http3.globalAgent),
1070
+ https: new TransformHeadersAgent(https2.globalAgent)
1071
+ },
1072
+ hooks: {
1073
+ init,
1074
+ beforeRequest,
1075
+ beforeRedirect
1076
+ }
1077
+ });
1078
+ var setupDecodeURI = /* @__PURE__ */ __name(() => {
1079
+ const { set } = Object.getOwnPropertyDescriptor(Options8.prototype, "url");
1080
+ Object.defineProperty(Options8.prototype, "url", {
1081
+ set(value) {
1082
+ const originalDecodeURI = global.decodeURI;
1083
+ global.decodeURI = (str) => str;
1084
+ try {
1085
+ return set.call(this, value);
1086
+ } finally {
1087
+ global.decodeURI = originalDecodeURI;
1088
+ }
1089
+ }
1090
+ });
1091
+ }, "setupDecodeURI");
1092
+ setupDecodeURI();
1093
+ var hooks = {
1094
+ init,
1095
+ beforeRequest,
1096
+ beforeRedirect,
1097
+ fixDecompress,
1098
+ insecureParserHook,
1099
+ sessionDataHook,
1100
+ http2Hook,
1101
+ proxyHook,
1102
+ browserHeadersHook,
1103
+ tlsHook,
1104
+ optionsValidationHandler,
1105
+ customOptionsHook,
1106
+ refererHook
1107
+ };
1108
+ export {
1109
+ TransformHeadersAgent,
1110
+ getAgents,
1111
+ gotScraping,
1112
+ hooks
1113
+ };
1114
+ //# sourceMappingURL=index.js.map