@depup/got-scraping 4.2.1-depup.0

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