-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Expand file tree
/
Copy pathlaunch-context.ts
More file actions
160 lines (147 loc) · 5.98 KB
/
Copy pathlaunch-context.ts
File metadata and controls
160 lines (147 loc) · 5.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
import type { Dictionary } from '@crawlee/types';
import type { BrowserFingerprintWithHeaders } from 'fingerprint-generator';
import type { BrowserPlugin, CommonBrowser, CommonLibrary } from './abstract-classes/browser-plugin';
import type { UnwrapPromise } from './utils';
/**
* `LaunchContext` holds information about the launched browser. It's useful
* to retrieve the `launchOptions`, the proxy the browser was launched with
* or any other information user chose to add to the `LaunchContext` by calling
* its `extend` function. This is very useful to keep track of browser-scoped
* values, such as session IDs.
*/
export interface LaunchContextOptions<
Library extends CommonLibrary = CommonLibrary,
LibraryOptions extends Dictionary | undefined = Parameters<Library['launch']>[0],
LaunchResult extends CommonBrowser = UnwrapPromise<ReturnType<Library['launch']>>,
NewPageOptions = Parameters<LaunchResult['newPage']>[0],
NewPageResult = UnwrapPromise<ReturnType<LaunchResult['newPage']>>,
> {
/**
* To make identification of `LaunchContext` easier, `BrowserPool` assigns
* the `LaunchContext` an `id` that's equal to the `id` of the page that
* triggered the browser launch. This is useful, because many pages share
* a single launch context (single browser).
*/
id?: string;
/**
* The `BrowserPlugin` instance used to launch the browser.
*/
browserPlugin: BrowserPlugin<Library, LibraryOptions, LaunchResult, NewPageOptions, NewPageResult>;
/**
* The actual options the browser was launched with, after changes.
* Those changes would be typically made in pre-launch hooks.
*/
launchOptions: LibraryOptions;
/**
* If set to `true`, the crawler respects the proxy url generated for the given request.
* This aligns the browser-based crawlers with the `HttpCrawler`.
*
* Might cause performance issues, as Crawlee might launch too many browser instances.
*/
browserPerProxy?: boolean;
/**
* By default pages share the same browser context.
* If set to `true` each page uses its own context that is destroyed once the page is closed or crashes.
*/
useIncognitoPages?: boolean;
/**
* @experimental
* Like `useIncognitoPages`, but for persistent contexts, so cache is used for faster loading.
* Works best with Firefox. Unstable on Chromium.
*/
experimentalContainers?: boolean;
/**
* Path to a User Data Directory, which stores browser session data like cookies and local storage.
*/
userDataDir?: string;
proxyUrl?: string;
proxyTier?: number;
/**
* If set to `true`, TLS certificate errors from the upstream proxy will be ignored.
* This is useful when using HTTPS proxies with self-signed certificates.
*/
ignoreProxyCertificate?: boolean;
}
export class LaunchContext<
Library extends CommonLibrary = CommonLibrary,
LibraryOptions extends Dictionary | undefined = Parameters<Library['launch']>[0],
LaunchResult extends CommonBrowser = UnwrapPromise<ReturnType<Library['launch']>>,
NewPageOptions = Parameters<LaunchResult['newPage']>[0],
NewPageResult = UnwrapPromise<ReturnType<LaunchResult['newPage']>>,
> {
id?: string;
browserPlugin: BrowserPlugin<Library, LibraryOptions, LaunchResult, NewPageOptions, NewPageResult>;
launchOptions: LibraryOptions;
useIncognitoPages: boolean;
browserPerProxy?: boolean;
experimentalContainers: boolean;
userDataDir: string;
proxyTier?: number;
ignoreProxyCertificate?: boolean;
private _proxyUrl?: string;
private readonly _reservedFieldNames = [...Reflect.ownKeys(this), 'extend'];
fingerprint?: BrowserFingerprintWithHeaders;
[K: PropertyKey]: unknown;
constructor(options: LaunchContextOptions<Library, LibraryOptions, LaunchResult, NewPageOptions, NewPageResult>) {
const {
id,
browserPlugin,
launchOptions,
proxyUrl,
useIncognitoPages,
browserPerProxy,
experimentalContainers,
userDataDir = '',
proxyTier,
ignoreProxyCertificate,
} = options;
this.id = id;
this.browserPlugin = browserPlugin;
this.launchOptions = launchOptions;
this.browserPerProxy = browserPerProxy ?? false;
this.useIncognitoPages = useIncognitoPages ?? false;
this.experimentalContainers = experimentalContainers ?? false;
this.userDataDir = userDataDir;
this.proxyTier = proxyTier;
this.ignoreProxyCertificate = ignoreProxyCertificate ?? false;
this._proxyUrl = proxyUrl;
}
/**
* Extend the launch context with any extra fields.
* This is useful to keep state information relevant
* to the browser being launched. It ensures that
* no internal fields are overridden and should be
* used instead of property assignment.
*/
extend<T extends Record<PropertyKey, unknown>>(fields: T): void {
Object.entries(fields).forEach(([key, value]) => {
if (this._reservedFieldNames.includes(key)) {
throw new Error(`Cannot extend LaunchContext with key: ${key}, because it's reserved.`);
} else {
Reflect.set(this, key, value);
}
});
}
/**
* Sets a proxy URL for the browser.
* Use `undefined` to unset existing proxy URL.
*/
set proxyUrl(url: string | undefined) {
if (!url) {
this._proxyUrl = undefined;
return;
}
const urlInstance = new URL(url);
urlInstance.pathname = '/';
urlInstance.search = '';
urlInstance.hash = '';
// https://www.chromium.org/developers/design-documents/network-settings/#command-line-options-for-proxy-settings
this._proxyUrl = urlInstance.href.slice(0, -1);
}
/**
* Returns the proxy URL of the browser.
*/
get proxyUrl(): string | undefined {
return this._proxyUrl;
}
}