@crawlee/browser-pool 4.0.0-beta.21 → 4.0.0-beta.210
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -14
- package/abstract-classes/browser-controller.d.ts +100 -29
- package/abstract-classes/browser-controller.js +70 -24
- package/abstract-classes/browser-plugin.d.ts +54 -23
- package/abstract-classes/browser-plugin.js +75 -13
- package/anonymize-proxy.d.ts +6 -2
- package/anonymize-proxy.js +9 -5
- package/browser-pool.d.ts +123 -49
- package/browser-pool.js +320 -147
- package/events.d.ts +2 -4
- package/events.js +0 -2
- package/fingerprinting/hooks.d.ts +0 -1
- package/fingerprinting/hooks.js +26 -10
- package/fingerprinting/types.d.ts +3 -34
- package/fingerprinting/types.js +0 -2
- package/fingerprinting/utils.d.ts +0 -1
- package/fingerprinting/utils.js +5 -6
- package/index.d.ts +14 -7
- package/index.js +5 -3
- package/launch-context.d.ts +21 -5
- package/launch-context.js +21 -10
- package/package.json +9 -9
- package/playwright/playwright-browser.d.ts +3 -6
- package/playwright/playwright-browser.js +17 -17
- package/playwright/playwright-controller.d.ts +1 -1
- package/playwright/playwright-controller.js +10 -6
- package/playwright/playwright-plugin.d.ts +12 -7
- package/playwright/playwright-plugin.js +42 -16
- package/proxy-server.d.ts +0 -1
- package/proxy-server.js +0 -1
- package/puppeteer/puppeteer-controller.d.ts +1 -1
- package/puppeteer/puppeteer-controller.js +29 -20
- package/puppeteer/puppeteer-plugin.d.ts +9 -3
- package/puppeteer/puppeteer-plugin.js +87 -46
- package/remote-browser-pool.d.ts +178 -0
- package/remote-browser-pool.js +206 -0
- package/remote-browser-provider.d.ts +83 -0
- package/remote-browser-provider.js +67 -0
- package/utils.d.ts +7 -1
- package/utils.js +19 -1
- package/abstract-classes/browser-controller.d.ts.map +0 -1
- package/abstract-classes/browser-controller.js.map +0 -1
- package/abstract-classes/browser-plugin.d.ts.map +0 -1
- package/abstract-classes/browser-plugin.js.map +0 -1
- package/anonymize-proxy.d.ts.map +0 -1
- package/anonymize-proxy.js.map +0 -1
- package/browser-pool.d.ts.map +0 -1
- package/browser-pool.js.map +0 -1
- package/container-proxy-server.d.ts +0 -12
- package/container-proxy-server.d.ts.map +0 -1
- package/container-proxy-server.js +0 -43
- package/container-proxy-server.js.map +0 -1
- package/events.d.ts.map +0 -1
- package/events.js.map +0 -1
- package/fingerprinting/hooks.d.ts.map +0 -1
- package/fingerprinting/hooks.js.map +0 -1
- package/fingerprinting/types.d.ts.map +0 -1
- package/fingerprinting/types.js.map +0 -1
- package/fingerprinting/utils.d.ts.map +0 -1
- package/fingerprinting/utils.js.map +0 -1
- package/index.d.ts.map +0 -1
- package/index.js.map +0 -1
- package/launch-context.d.ts.map +0 -1
- package/launch-context.js.map +0 -1
- package/logger.d.ts +0 -3
- package/logger.d.ts.map +0 -1
- package/logger.js +0 -5
- package/logger.js.map +0 -1
- package/playwright/playwright-browser.d.ts.map +0 -1
- package/playwright/playwright-browser.js.map +0 -1
- package/playwright/playwright-controller.d.ts.map +0 -1
- package/playwright/playwright-controller.js.map +0 -1
- package/playwright/playwright-plugin.d.ts.map +0 -1
- package/playwright/playwright-plugin.js.map +0 -1
- package/proxy-server.d.ts.map +0 -1
- package/proxy-server.js.map +0 -1
- package/puppeteer/puppeteer-controller.d.ts.map +0 -1
- package/puppeteer/puppeteer-controller.js.map +0 -1
- package/puppeteer/puppeteer-plugin.d.ts.map +0 -1
- package/puppeteer/puppeteer-plugin.js.map +0 -1
- package/utils.d.ts.map +0 -1
- package/utils.js.map +0 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { CriticalError } from '@crawlee/core';
|
|
1
|
+
import { CriticalError, serviceLocator } from '@crawlee/core';
|
|
2
2
|
import merge from 'lodash.merge';
|
|
3
3
|
import { LaunchContext } from '../launch-context.js';
|
|
4
|
+
import { sanitizeEndpointForLog } from '../utils.js';
|
|
4
5
|
/**
|
|
5
6
|
* The default User Agent used by `PlaywrightCrawler`, `launchPlaywright`, 'PuppeteerCrawler' and 'launchPuppeteer'
|
|
6
7
|
* when Chromium/Chrome browser is launched:
|
|
@@ -8,8 +9,6 @@ import { LaunchContext } from '../launch-context.js';
|
|
|
8
9
|
* - without using a fingerprint,
|
|
9
10
|
* - without specifying a user agent.
|
|
10
11
|
* Last updated on 2022-05-05.
|
|
11
|
-
*
|
|
12
|
-
* After you update it here, please update it also in jsdom-crawler.ts
|
|
13
12
|
*/
|
|
14
13
|
export const DEFAULT_USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36';
|
|
15
14
|
/**
|
|
@@ -20,20 +19,79 @@ export const DEFAULT_USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_
|
|
|
20
19
|
*/
|
|
21
20
|
export class BrowserPlugin {
|
|
22
21
|
name = this.constructor.name;
|
|
22
|
+
/**
|
|
23
|
+
* Kept `protected` rather than `#private` because the concrete plugins in this package are separate
|
|
24
|
+
* classes — an ES private field would not be visible to them.
|
|
25
|
+
*
|
|
26
|
+
* @internal
|
|
27
|
+
*/
|
|
28
|
+
log;
|
|
23
29
|
library;
|
|
24
30
|
launchOptions;
|
|
25
31
|
proxyUrl;
|
|
26
32
|
userDataDir;
|
|
27
33
|
useIncognitoPages;
|
|
28
34
|
browserPerProxy;
|
|
35
|
+
ignoreProxyCertificate;
|
|
36
|
+
/**
|
|
37
|
+
* Set by {@link RemoteBrowserPool} when this plugin connects to a remote browser service instead of
|
|
38
|
+
* launching locally. Holds the bridge the plugin uses to resolve endpoints and release sessions; all
|
|
39
|
+
* remote-session policy lives in the pool, not here.
|
|
40
|
+
*
|
|
41
|
+
* @internal
|
|
42
|
+
*/
|
|
43
|
+
remoteConnection;
|
|
44
|
+
/** Static connect() parameters for a remote connection (protocol, headers, …). @internal */
|
|
45
|
+
remoteConnectionParameters;
|
|
29
46
|
constructor(library, options = {}) {
|
|
30
|
-
const { launchOptions = {}, proxyUrl, userDataDir, useIncognitoPages = false, browserPerProxy = false, } = options;
|
|
47
|
+
const { launchOptions = {}, proxyUrl, userDataDir, useIncognitoPages = false, browserPerProxy = false, ignoreProxyCertificate = false, } = options;
|
|
48
|
+
this.log = serviceLocator.getLogger().child({ prefix: 'BrowserPool' });
|
|
31
49
|
this.library = library;
|
|
32
50
|
this.launchOptions = launchOptions;
|
|
33
51
|
this.proxyUrl = proxyUrl && new URL(proxyUrl).href.slice(0, -1);
|
|
34
52
|
this.userDataDir = userDataDir;
|
|
35
53
|
this.useIncognitoPages = useIncognitoPages;
|
|
36
54
|
this.browserPerProxy = browserPerProxy;
|
|
55
|
+
this.ignoreProxyCertificate = ignoreProxyCertificate;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Configures this plugin to connect to a remote browser using the given {@link RemoteConnection}.
|
|
59
|
+
* Called by {@link RemoteBrowserPool}; subclasses may override to apply library-specific defaults
|
|
60
|
+
* (e.g. forcing incognito pages).
|
|
61
|
+
*
|
|
62
|
+
* @internal
|
|
63
|
+
*/
|
|
64
|
+
useRemoteConnection(connection, parameters = {}) {
|
|
65
|
+
this.remoteConnection = connection;
|
|
66
|
+
this.remoteConnectionParameters = parameters;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Resolves a remote endpoint via the injected {@link RemoteConnection}, stores the session token on
|
|
70
|
+
* the launch context (so the controller can release it on close), and runs the library-specific `connect`.
|
|
71
|
+
* On failure the session is released and the error is wrapped in a {@link BrowserLaunchError}.
|
|
72
|
+
*
|
|
73
|
+
* Subclasses implement only the `connect` callback — the resolve / token / release / error-wrap scaffolding
|
|
74
|
+
* lives here so it stays identical across plugins.
|
|
75
|
+
*/
|
|
76
|
+
async connectToRemoteBrowser(launchContext, connect) {
|
|
77
|
+
const connection = this.remoteConnection;
|
|
78
|
+
let url;
|
|
79
|
+
let token;
|
|
80
|
+
try {
|
|
81
|
+
({ url, token } = await connection.resolve({ proxyUrl: launchContext.proxyUrl }));
|
|
82
|
+
}
|
|
83
|
+
catch (cause) {
|
|
84
|
+
throw new BrowserLaunchError('Failed to resolve the remote browser endpoint.', { cause });
|
|
85
|
+
}
|
|
86
|
+
launchContext.remoteToken = token;
|
|
87
|
+
try {
|
|
88
|
+
return await connect(url);
|
|
89
|
+
}
|
|
90
|
+
catch (cause) {
|
|
91
|
+
await connection.release(token);
|
|
92
|
+
throw new BrowserLaunchError(`Failed to connect to remote browser at "${sanitizeEndpointForLog(url)}". ` +
|
|
93
|
+
'Check that the endpoint is reachable and accepts the configured protocol.', { cause });
|
|
94
|
+
}
|
|
37
95
|
}
|
|
38
96
|
/**
|
|
39
97
|
* Creates a `LaunchContext` with all the information needed
|
|
@@ -42,7 +100,7 @@ export class BrowserPlugin {
|
|
|
42
100
|
* management of the pool and extra features.
|
|
43
101
|
*/
|
|
44
102
|
createLaunchContext(options = {}) {
|
|
45
|
-
const { id, launchOptions = {}, proxyUrl = this.proxyUrl, useIncognitoPages = this.useIncognitoPages, userDataDir = this.userDataDir, browserPerProxy = this.browserPerProxy,
|
|
103
|
+
const { id, launchOptions = {}, proxyUrl = this.proxyUrl, useIncognitoPages = this.useIncognitoPages, userDataDir = this.userDataDir, browserPerProxy = this.browserPerProxy, ignoreProxyCertificate = this.ignoreProxyCertificate, isRemote = !!this.remoteConnection, } = options;
|
|
46
104
|
return new LaunchContext({
|
|
47
105
|
id,
|
|
48
106
|
launchOptions: merge({}, this.launchOptions, launchOptions),
|
|
@@ -51,21 +109,23 @@ export class BrowserPlugin {
|
|
|
51
109
|
useIncognitoPages,
|
|
52
110
|
userDataDir,
|
|
53
111
|
browserPerProxy,
|
|
54
|
-
|
|
112
|
+
ignoreProxyCertificate,
|
|
113
|
+
isRemote,
|
|
55
114
|
});
|
|
56
115
|
}
|
|
57
116
|
/**
|
|
58
117
|
* Launches the browser using provided launch context.
|
|
59
118
|
*/
|
|
60
119
|
async launch(launchContext = this.createLaunchContext()) {
|
|
120
|
+
// launchOptions is only used by the local launch path below — remote connections ignore it.
|
|
61
121
|
launchContext.launchOptions ??= {};
|
|
62
122
|
const { proxyUrl, launchOptions } = launchContext;
|
|
63
|
-
if (proxyUrl) {
|
|
64
|
-
await this.
|
|
123
|
+
if (proxyUrl && !launchContext.isRemote) {
|
|
124
|
+
await this.addProxyToLaunchOptions(launchContext);
|
|
65
125
|
}
|
|
66
|
-
if (this.
|
|
126
|
+
if (!launchContext.isRemote && this.isChromiumBasedBrowser(launchContext)) {
|
|
67
127
|
// This will set the args for chromium based browsers to hide the webdriver.
|
|
68
|
-
launchOptions.args = this.
|
|
128
|
+
launchOptions.args = this.mergeArgsToHideWebdriver(launchOptions.args);
|
|
69
129
|
// When User-Agent is not set, and we're using Chromium in headless mode,
|
|
70
130
|
// it is better to use DEFAULT_USER_AGENT to reduce chance of detection,
|
|
71
131
|
// as otherwise 'HeadlessChrome' is present in User-Agent string.
|
|
@@ -74,9 +134,12 @@ export class BrowserPlugin {
|
|
|
74
134
|
launchOptions.args.push(`--user-agent=${DEFAULT_USER_AGENT}`);
|
|
75
135
|
}
|
|
76
136
|
}
|
|
137
|
+
if (launchContext.isRemote) {
|
|
138
|
+
this.log.info('Connecting to remote browser (skipping local proxy and webdriver stealth configuration).');
|
|
139
|
+
}
|
|
77
140
|
return this._launch(launchContext);
|
|
78
141
|
}
|
|
79
|
-
|
|
142
|
+
mergeArgsToHideWebdriver(originalArgs) {
|
|
80
143
|
if (!originalArgs?.length) {
|
|
81
144
|
return ['--disable-blink-features=AutomationControlled'];
|
|
82
145
|
}
|
|
@@ -89,7 +152,7 @@ export class BrowserPlugin {
|
|
|
89
152
|
}
|
|
90
153
|
return originalArgs;
|
|
91
154
|
}
|
|
92
|
-
|
|
155
|
+
throwAugmentedLaunchError(cause, executablePath, dockerImage, moduleInstallCommand) {
|
|
93
156
|
const errorMessage = ['Failed to launch browser. Please check the following:'];
|
|
94
157
|
if (executablePath) {
|
|
95
158
|
errorMessage.push(`- Check whether the provided executable path "${executablePath}" is correct.`);
|
|
@@ -118,4 +181,3 @@ export class BrowserLaunchError extends CriticalError {
|
|
|
118
181
|
});
|
|
119
182
|
}
|
|
120
183
|
}
|
|
121
|
-
//# sourceMappingURL=browser-plugin.js.map
|
package/anonymize-proxy.d.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
type PromiseVoid = () => Promise<void>;
|
|
2
|
-
|
|
2
|
+
/** @internal */
|
|
3
|
+
export interface AnonymizeProxySugarOptions {
|
|
4
|
+
ignoreProxyCertificate?: boolean;
|
|
5
|
+
}
|
|
6
|
+
/** @internal */
|
|
7
|
+
export declare const anonymizeProxySugar: (proxyUrl?: string, username?: string, password?: string, options?: AnonymizeProxySugarOptions) => Promise<[string | undefined, PromiseVoid]>;
|
|
3
8
|
export {};
|
|
4
|
-
//# sourceMappingURL=anonymize-proxy.d.ts.map
|
package/anonymize-proxy.js
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
export const anonymizeProxySugar = async (proxyUrl, username, password) => {
|
|
1
|
+
/** @internal */
|
|
2
|
+
export const anonymizeProxySugar = async (proxyUrl, username, password, options) => {
|
|
3
3
|
if (proxyUrl) {
|
|
4
4
|
const url = new URL(proxyUrl);
|
|
5
5
|
if (username || password) {
|
|
6
6
|
url.username = username ?? '';
|
|
7
7
|
url.password = password ?? '';
|
|
8
8
|
}
|
|
9
|
-
if (url.username || url.password) {
|
|
9
|
+
if (url.username || url.password || options?.ignoreProxyCertificate) {
|
|
10
10
|
// trim off trailing slash if it's present
|
|
11
11
|
const proxyUrlString = url.href.endsWith('/') ? url.href.slice(0, -1) : url.href;
|
|
12
|
-
const
|
|
12
|
+
const { anonymizeProxy, closeAnonymizedProxy } = await import('proxy-chain');
|
|
13
|
+
const anonymized = await anonymizeProxy({
|
|
14
|
+
url: proxyUrlString,
|
|
15
|
+
port: 0,
|
|
16
|
+
ignoreProxyCertificate: options?.ignoreProxyCertificate ?? false,
|
|
17
|
+
});
|
|
13
18
|
return [
|
|
14
19
|
anonymized,
|
|
15
20
|
async () => {
|
|
@@ -21,4 +26,3 @@ export const anonymizeProxySugar = async (proxyUrl, username, password) => {
|
|
|
21
26
|
}
|
|
22
27
|
return [undefined, async () => { }];
|
|
23
28
|
};
|
|
24
|
-
//# sourceMappingURL=anonymize-proxy.js.map
|
package/browser-pool.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { IBrowserPool, NewPageOptions, PageState } from '@crawlee/types';
|
|
1
2
|
import type { BrowserFingerprintWithHeaders } from 'fingerprint-generator';
|
|
2
3
|
import { FingerprintGenerator } from 'fingerprint-generator';
|
|
3
4
|
import { FingerprintInjector } from 'fingerprint-injector';
|
|
@@ -246,38 +247,39 @@ export interface BrowserPoolHooks<BC extends BrowserController, LC extends Launc
|
|
|
246
247
|
* });
|
|
247
248
|
* ```
|
|
248
249
|
*/
|
|
249
|
-
export declare class BrowserPool<Options extends BrowserPoolOptions = BrowserPoolOptions, BrowserPlugins extends BrowserPlugin[] = InferBrowserPluginArray<Options['browserPlugins']>, BrowserControllerReturn extends BrowserController = ReturnType<BrowserPlugins[number]['createController']>, LaunchContextReturn extends LaunchContext = ReturnType<BrowserPlugins[number]['createLaunchContext']>, PageOptions = Parameters<BrowserControllerReturn['newPage']>[0], PageReturn extends UnwrapPromise<ReturnType<BrowserControllerReturn['newPage']>> = UnwrapPromise<ReturnType<BrowserControllerReturn['newPage']>>> extends TypedEmitter<BrowserPoolEvents<BrowserControllerReturn, PageReturn>> {
|
|
250
|
+
export declare class BrowserPool<Options extends BrowserPoolOptions = BrowserPoolOptions, BrowserPlugins extends BrowserPlugin[] = InferBrowserPluginArray<Options['browserPlugins']>, BrowserControllerReturn extends BrowserController = ReturnType<BrowserPlugins[number]['createController']>, LaunchContextReturn extends LaunchContext = ReturnType<BrowserPlugins[number]['createLaunchContext']>, PageOptions = Parameters<BrowserControllerReturn['newPage']>[0], PageReturn extends UnwrapPromise<ReturnType<BrowserControllerReturn['newPage']>> = UnwrapPromise<ReturnType<BrowserControllerReturn['newPage']>>> extends TypedEmitter<BrowserPoolEvents<BrowserControllerReturn, PageReturn>> implements IBrowserPool<PageReturn> {
|
|
251
|
+
#private;
|
|
250
252
|
browserPlugins: BrowserPlugins;
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
closeInactiveBrowserAfterMillis: number;
|
|
255
|
-
useFingerprints?: boolean;
|
|
253
|
+
/** @internal */
|
|
254
|
+
maxOpenBrowsers: number;
|
|
255
|
+
/** @internal */
|
|
256
256
|
fingerprintOptions: FingerprintOptions;
|
|
257
|
-
|
|
258
|
-
postLaunchHooks: PostLaunchHook<BrowserControllerReturn>[];
|
|
259
|
-
prePageCreateHooks: PrePageCreateHook<BrowserControllerReturn, PageOptions>[];
|
|
260
|
-
postPageCreateHooks: PostPageCreateHook<BrowserControllerReturn, PageReturn>[];
|
|
261
|
-
prePageCloseHooks: PrePageCloseHook<BrowserControllerReturn, PageReturn>[];
|
|
262
|
-
postPageCloseHooks: PostPageCloseHook<BrowserControllerReturn>[];
|
|
263
|
-
pageCounter: number;
|
|
264
|
-
pages: Map<string, PageReturn>;
|
|
265
|
-
pageIds: WeakMap<PageReturn, string>;
|
|
266
|
-
startingBrowserControllers: Set<BrowserControllerReturn>;
|
|
267
|
-
activeBrowserControllers: Set<BrowserControllerReturn>;
|
|
268
|
-
retiredBrowserControllers: Set<BrowserControllerReturn>;
|
|
269
|
-
pageToBrowserController: WeakMap<PageReturn, BrowserControllerReturn>;
|
|
257
|
+
/** @internal */
|
|
270
258
|
fingerprintInjector?: FingerprintInjector;
|
|
271
259
|
fingerprintGenerator?: FingerprintGenerator;
|
|
260
|
+
/** @internal */
|
|
272
261
|
fingerprintCache?: QuickLRU<string, BrowserFingerprintWithHeaders>;
|
|
262
|
+
private pages;
|
|
263
|
+
private activeBrowserControllers;
|
|
264
|
+
private retiredBrowserControllers;
|
|
273
265
|
private browserKillerInterval?;
|
|
274
|
-
private browserRetireInterval?;
|
|
275
|
-
private limiter;
|
|
276
266
|
constructor(options: Options & BrowserPoolHooks<BrowserControllerReturn, LaunchContextReturn, PageReturn>);
|
|
277
267
|
/**
|
|
278
268
|
* Opens a new page in one of the running browsers or launches
|
|
279
269
|
* a new browser and opens a page there, if no browsers are active,
|
|
280
270
|
* or their page limits have been exceeded.
|
|
271
|
+
*
|
|
272
|
+
* **Session injection (best-effort):** When a {@link NewPageOptions.session|session} is
|
|
273
|
+
* provided, this implementation uses it as a cache key for browser fingerprints (when
|
|
274
|
+
* fingerprinting is enabled) and reads
|
|
275
|
+
* {@link ProxyInfo.url|session.proxyInfo.url} /
|
|
276
|
+
* {@link ProxyInfo.ignoreTlsErrors|session.proxyInfo.ignoreTlsErrors} as defaults
|
|
277
|
+
* for `proxyUrl` and `ignoreTlsErrors` respectively. Explicit `proxyUrl` /
|
|
278
|
+
* `ignoreTlsErrors` values in the options take precedence.
|
|
279
|
+
*
|
|
280
|
+
* Beyond fingerprint caching and proxy configuration, no other session
|
|
281
|
+
* properties are consumed — cookie and header injection remain the
|
|
282
|
+
* crawler's responsibility.
|
|
281
283
|
*/
|
|
282
284
|
newPage(options?: BrowserPoolNewPageOptions<PageOptions, BrowserPlugins[number]>): Promise<PageReturn>;
|
|
283
285
|
/**
|
|
@@ -335,7 +337,7 @@ export declare class BrowserPool<Options extends BrowserPoolOptions = BrowserPoo
|
|
|
335
337
|
* until it's closed.
|
|
336
338
|
*/
|
|
337
339
|
getPageId(page: PageReturn): string | undefined;
|
|
338
|
-
private
|
|
340
|
+
private createPageForBrowser;
|
|
339
341
|
/**
|
|
340
342
|
* Removes a browser controller from the pool. The underlying
|
|
341
343
|
* browser will be closed after all its pages are closed.
|
|
@@ -347,6 +349,44 @@ export declare class BrowserPool<Options extends BrowserPoolOptions = BrowserPoo
|
|
|
347
349
|
* closed after all its pages are closed.
|
|
348
350
|
*/
|
|
349
351
|
retireBrowserByPage(page: PageReturn): void;
|
|
352
|
+
/**
|
|
353
|
+
* Releases a page back to the pool. The page is closed and, if the
|
|
354
|
+
* optional `error` is a {@link SessionError} (including
|
|
355
|
+
* {@link SessionRetiredError}), the browser controller that served
|
|
356
|
+
* the page is retired so that the finished session's state (cookies,
|
|
357
|
+
* storage, etc.) cannot leak into future sessions.
|
|
358
|
+
*
|
|
359
|
+
* This is the primary way the crawler should return pages to the pool.
|
|
360
|
+
*
|
|
361
|
+
* @param page The page to release.
|
|
362
|
+
* @param options.error The error that caused the page to be released, if any.
|
|
363
|
+
*/
|
|
364
|
+
closePage(page: PageReturn, options?: {
|
|
365
|
+
error?: Error;
|
|
366
|
+
}): Promise<void>;
|
|
367
|
+
/**
|
|
368
|
+
* Extracts the relevant state (currently just cookies) from a page via its
|
|
369
|
+
* owning {@link BrowserController}. Returns empty state when the page is
|
|
370
|
+
* no longer associated with a controller.
|
|
371
|
+
*
|
|
372
|
+
* As with {@link BrowserPool.injectPageState}, cookies are isolated per
|
|
373
|
+
* page only when the pool is configured with `useIncognitoPages: true`.
|
|
374
|
+
* With the default `useIncognitoPages: false`, the extracted cookies
|
|
375
|
+
* include those set by any sibling page sharing the same browser.
|
|
376
|
+
*/
|
|
377
|
+
extractPageState(page: PageReturn): Promise<PageState>;
|
|
378
|
+
/**
|
|
379
|
+
* Injects state into a page via its owning {@link BrowserController}.
|
|
380
|
+
*
|
|
381
|
+
* No-op when the page is no longer associated with a controller.
|
|
382
|
+
*
|
|
383
|
+
* Note that cookies are isolated per page only when the pool is configured
|
|
384
|
+
* with `useIncognitoPages: true` — each page then gets its own browser
|
|
385
|
+
* context. With the default `useIncognitoPages: false`, all pages in a
|
|
386
|
+
* browser share a single context, so injected cookies are visible to every
|
|
387
|
+
* page served by that browser.
|
|
388
|
+
*/
|
|
389
|
+
injectPageState(page: PageReturn, state: PageState): Promise<void>;
|
|
350
390
|
/**
|
|
351
391
|
* Removes all active browsers from the pool. The browsers will be
|
|
352
392
|
* closed after all their pages are closed.
|
|
@@ -357,32 +397,75 @@ export declare class BrowserPool<Options extends BrowserPoolOptions = BrowserPoo
|
|
|
357
397
|
* @return {Promise<void>}
|
|
358
398
|
*/
|
|
359
399
|
closeAllBrowsers(): Promise<void>;
|
|
400
|
+
[Symbol.asyncDispose](): Promise<void>;
|
|
360
401
|
/**
|
|
361
|
-
* Closes
|
|
402
|
+
* Closes every managed browser and empties the pool, which stays usable afterwards — a crawler releases its
|
|
403
|
+
* browsers when a run ends and may start another run on the same pool.
|
|
404
|
+
*/
|
|
405
|
+
releaseAllBrowsers(): Promise<void>;
|
|
406
|
+
/**
|
|
407
|
+
* Closes all managed browsers and tears the pool down for good: its intervals are cleared without being
|
|
408
|
+
* re-armed and its listeners are dropped, so it cannot be used again.
|
|
362
409
|
*/
|
|
363
410
|
destroy(): Promise<void>;
|
|
364
|
-
private
|
|
365
|
-
private
|
|
366
|
-
private _launchBrowser;
|
|
411
|
+
private getAllBrowserControllers;
|
|
412
|
+
private launchBrowser;
|
|
367
413
|
/**
|
|
368
414
|
* Picks plugins round robin.
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
private
|
|
372
|
-
private
|
|
373
|
-
private
|
|
374
|
-
private
|
|
375
|
-
private
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
415
|
+
*/
|
|
416
|
+
private pickBrowserPlugin;
|
|
417
|
+
private pickBrowserWithFreeCapacity;
|
|
418
|
+
private closeInactiveRetiredBrowsers;
|
|
419
|
+
private overridePageClose;
|
|
420
|
+
private executeHooks;
|
|
421
|
+
private closeRetiredBrowserWithNoPages;
|
|
422
|
+
/**
|
|
423
|
+
* Returns `true` if the pool can accept a new browser launch without exceeding `maxOpenBrowsers`.
|
|
424
|
+
* Counts starting, active, and retired browsers.
|
|
425
|
+
*
|
|
426
|
+
* A plain `BrowserPool` leaves `maxOpenBrowsers` at `Infinity`, so this only returns `false` when something
|
|
427
|
+
* has set a cap — {@link RemoteBrowserPool} does, from its own
|
|
428
|
+
* {@link RemoteBrowserPoolOptions.maxOpenBrowsers|`maxOpenBrowsers`} option. There is no
|
|
429
|
+
* `BrowserPoolOptions` key for it.
|
|
430
|
+
*
|
|
431
|
+
* @internal
|
|
432
|
+
*/
|
|
433
|
+
hasFreeBrowserSlot(): boolean;
|
|
434
|
+
/**
|
|
435
|
+
* Returns `true` if any active browser has room for another page.
|
|
436
|
+
*
|
|
437
|
+
* @internal
|
|
438
|
+
*/
|
|
439
|
+
hasActiveBrowserWithFreeCapacity(): boolean;
|
|
440
|
+
private initializeFingerprinting;
|
|
379
441
|
}
|
|
380
|
-
export interface BrowserPoolNewPageOptions<PageOptions, BP extends BrowserPlugin> {
|
|
442
|
+
export interface BrowserPoolNewPageOptions<PageOptions, BP extends BrowserPlugin> extends NewPageOptions {
|
|
443
|
+
/**
|
|
444
|
+
* The proxy URL the pool uses internally to route the page: it keys browser
|
|
445
|
+
* reuse (with `browserPerProxy`, only a browser already on this proxy is
|
|
446
|
+
* reused), configures the launched browser, and is applied to incognito
|
|
447
|
+
* pages. When omitted, it is derived from the
|
|
448
|
+
* {@link NewPageOptions.session|session}'s `proxyInfo`; an explicit value
|
|
449
|
+
* here takes precedence.
|
|
450
|
+
*
|
|
451
|
+
* This is an implementation detail of the built-in `BrowserPool`'s proxy
|
|
452
|
+
* handling and is intentionally not part of the {@link IBrowserPool}
|
|
453
|
+
* contract — through that interface the proxy is supplied via the session.
|
|
454
|
+
*/
|
|
455
|
+
proxyUrl?: string;
|
|
381
456
|
/**
|
|
382
|
-
*
|
|
383
|
-
*
|
|
457
|
+
* Disable TLS certificate verification for MITM proxies. Applied both when
|
|
458
|
+
* launching a new browser and when creating a page in an existing one. When
|
|
459
|
+
* omitted, it is derived from the
|
|
460
|
+
* {@link NewPageOptions.session|session}'s `proxyInfo`; an explicit value
|
|
461
|
+
* here takes precedence.
|
|
462
|
+
*
|
|
463
|
+
* This is an implementation detail of the built-in `BrowserPool` and is
|
|
464
|
+
* intentionally not part of the {@link IBrowserPool} contract — through
|
|
465
|
+
* that interface, configure it via the session's `proxyInfo` or through the
|
|
466
|
+
* browser's `launchOptions`.
|
|
384
467
|
*/
|
|
385
|
-
|
|
468
|
+
ignoreTlsErrors?: boolean;
|
|
386
469
|
/**
|
|
387
470
|
* Some libraries (Playwright) allow you to open new pages with specific
|
|
388
471
|
* options. Use this property to set those options.
|
|
@@ -397,14 +480,6 @@ export interface BrowserPoolNewPageOptions<PageOptions, BP extends BrowserPlugin
|
|
|
397
480
|
* see the `newPageInNewBrowser` function.
|
|
398
481
|
*/
|
|
399
482
|
browserPlugin?: BP;
|
|
400
|
-
/**
|
|
401
|
-
* Proxy URL.
|
|
402
|
-
*/
|
|
403
|
-
proxyUrl?: string;
|
|
404
|
-
/**
|
|
405
|
-
* Proxy tier.
|
|
406
|
-
*/
|
|
407
|
-
proxyTier?: number;
|
|
408
483
|
}
|
|
409
484
|
export interface BrowserPoolNewPageInNewBrowserOptions<PageOptions, BP extends BrowserPlugin> {
|
|
410
485
|
/**
|
|
@@ -435,4 +510,3 @@ export interface BrowserPoolNewPageInNewBrowserOptions<PageOptions, BP extends B
|
|
|
435
510
|
*/
|
|
436
511
|
launchOptions?: BP['launchOptions'];
|
|
437
512
|
}
|
|
438
|
-
//# sourceMappingURL=browser-pool.d.ts.map
|