@browserless.io/browserless 2.12.0-beta-4 → 2.12.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/CHANGELOG.md +9 -1
- package/bin/scaffold/README.md +6 -5
- package/bin/scaffold/src/hello-world.http.ts +3 -3
- package/build/browserless.d.ts +3 -3
- package/build/browserless.js +6 -6
- package/build/browsers/chromium.cdp.d.ts +12 -12
- package/build/browsers/chromium.cdp.js +77 -65
- package/build/browsers/chromium.playwright.d.ts +11 -11
- package/build/browsers/chromium.playwright.js +42 -34
- package/build/browsers/firefox.playwright.d.ts +11 -11
- package/build/browsers/firefox.playwright.js +42 -34
- package/build/browsers/index.d.ts +14 -14
- package/build/browsers/index.js +27 -25
- package/build/browsers/webkit.playwright.d.ts +11 -11
- package/build/browsers/webkit.playwright.js +43 -35
- package/build/config.d.ts +65 -63
- package/build/config.js +162 -102
- package/build/file-system.d.ts +4 -4
- package/build/file-system.js +8 -8
- package/build/hooks.d.ts +2 -2
- package/build/hooks.js +4 -4
- package/build/limiter.d.ts +4 -4
- package/build/limiter.js +10 -10
- package/build/logger.d.ts +6 -6
- package/build/logger.js +12 -12
- package/build/metrics.d.ts +12 -12
- package/build/metrics.js +23 -23
- package/build/monitoring.d.ts +4 -4
- package/build/monitoring.js +8 -8
- package/build/router.d.ts +8 -8
- package/build/router.js +74 -70
- package/build/routes/chrome/http/pdf.post.body.json +8 -8
- package/build/routes/chrome/http/scrape.post.body.json +8 -8
- package/build/routes/chrome/http/screenshot.post.body.json +8 -8
- package/build/routes/chromium/http/content.post.body.json +8 -8
- package/build/routes/chromium/http/pdf.post.body.json +8 -8
- package/build/routes/chromium/http/scrape.post.body.json +8 -8
- package/build/routes/chromium/http/screenshot.post.body.json +8 -8
- package/build/routes/firefox/ws/playwright.d.ts +1 -1
- package/build/routes/firefox/ws/playwright.js +2 -2
- package/build/routes/management/http/active.get.d.ts +1 -1
- package/build/routes/management/http/active.get.js +3 -1
- package/build/routes/management/http/config.get.d.ts +1 -1
- package/build/routes/management/http/config.get.js +2 -2
- package/build/routes/management/http/metrics-total.get.d.ts +1 -1
- package/build/routes/management/http/metrics-total.get.js +2 -2
- package/build/routes/management/http/metrics.get.d.ts +1 -1
- package/build/routes/management/http/metrics.get.js +2 -2
- package/build/routes/management/http/pressure.get.d.ts +1 -1
- package/build/routes/management/http/pressure.get.js +2 -2
- package/build/routes/management/http/sessions.get.d.ts +1 -1
- package/build/routes/management/http/sessions.get.js +2 -2
- package/build/routes/management/http/static.get.d.ts +1 -1
- package/build/routes/management/http/static.get.js +2 -2
- package/build/routes/webkit/ws/playwright.d.ts +1 -1
- package/build/routes/webkit/ws/playwright.js +2 -2
- package/build/server.d.ts +5 -5
- package/build/server.js +11 -11
- package/build/shared/browser.ws.d.ts +1 -1
- package/build/shared/browser.ws.js +3 -1
- package/build/shared/chromium.playwright.ws.d.ts +1 -1
- package/build/shared/chromium.playwright.ws.js +2 -2
- package/build/shared/chromium.ws.d.ts +1 -1
- package/build/shared/chromium.ws.js +3 -1
- package/build/shared/content.http.d.ts +1 -1
- package/build/shared/content.http.js +2 -2
- package/build/shared/download.http.d.ts +1 -1
- package/build/shared/download.http.js +60 -58
- package/build/shared/function.http.d.ts +1 -1
- package/build/shared/function.http.js +2 -2
- package/build/shared/json-list.http.d.ts +1 -1
- package/build/shared/json-list.http.js +2 -2
- package/build/shared/json-new.http.d.ts +1 -1
- package/build/shared/json-new.http.js +2 -2
- package/build/shared/json-protocol.http.d.ts +1 -1
- package/build/shared/json-protocol.http.js +2 -2
- package/build/shared/json-version.http.d.ts +1 -1
- package/build/shared/json-version.http.js +2 -2
- package/build/shared/page.ws.d.ts +1 -1
- package/build/shared/page.ws.js +3 -1
- package/build/shared/pdf.http.d.ts +1 -1
- package/build/shared/pdf.http.js +2 -2
- package/build/shared/performance.http.d.ts +1 -1
- package/build/shared/performance.http.js +2 -2
- package/build/shared/scrape.http.d.ts +1 -1
- package/build/shared/scrape.http.js +2 -2
- package/build/shared/screenshot.http.d.ts +1 -1
- package/build/shared/screenshot.http.js +2 -2
- package/build/shared/utils/function/client.d.ts +1 -1
- package/build/shared/utils/function/client.js +3 -1
- package/build/shim.d.ts +1 -1
- package/build/shim.js +2 -2
- package/build/token.d.ts +3 -3
- package/build/token.js +6 -6
- package/build/types.d.ts +4 -4
- package/build/webhooks.d.ts +2 -2
- package/build/webhooks.js +4 -4
- package/package.json +3 -3
- package/src/browserless.ts +6 -6
- package/src/browsers/chromium.cdp.ts +33 -23
- package/src/browsers/chromium.playwright.ts +28 -21
- package/src/browsers/firefox.playwright.ts +28 -21
- package/src/browsers/index.ts +32 -29
- package/src/browsers/webkit.playwright.ts +29 -22
- package/src/config.ts +166 -104
- package/src/file-system.ts +9 -9
- package/src/hooks.ts +4 -4
- package/src/limiter.ts +12 -12
- package/src/logger.ts +12 -12
- package/src/metrics.ts +23 -23
- package/src/monitoring.ts +9 -9
- package/src/router.ts +31 -31
- package/src/routes/firefox/ws/playwright.ts +3 -3
- package/src/routes/management/http/active.get.ts +3 -2
- package/src/routes/management/http/config.get.ts +2 -2
- package/src/routes/management/http/metrics-total.get.ts +2 -2
- package/src/routes/management/http/metrics.get.ts +2 -2
- package/src/routes/management/http/pressure.get.ts +2 -2
- package/src/routes/management/http/sessions.get.ts +2 -2
- package/src/routes/management/http/static.get.ts +3 -3
- package/src/routes/webkit/ws/playwright.ts +3 -3
- package/src/server.ts +14 -16
- package/src/shared/browser.ws.ts +4 -2
- package/src/shared/chromium.playwright.ws.ts +3 -3
- package/src/shared/chromium.ws.ts +4 -2
- package/src/shared/content.http.ts +3 -3
- package/src/shared/download.http.ts +4 -3
- package/src/shared/function.http.ts +3 -3
- package/src/shared/json-list.http.ts +2 -2
- package/src/shared/json-new.http.ts +2 -2
- package/src/shared/json-protocol.http.ts +2 -6
- package/src/shared/json-version.http.ts +2 -6
- package/src/shared/page.ws.ts +4 -2
- package/src/shared/pdf.http.ts +3 -3
- package/src/shared/performance.http.ts +3 -3
- package/src/shared/scrape.http.ts +3 -3
- package/src/shared/screenshot.http.ts +3 -3
- package/src/shared/utils/function/client.ts +3 -1
- package/src/shim.ts +2 -2
- package/src/token.ts +7 -7
- package/src/types.ts +7 -7
- package/src/webhooks.ts +4 -4
- package/static/docs/swagger.json +2 -2
- package/static/docs/swagger.min.json +1 -1
- package/static/function/client.js +3 -1
- package/static/function/index.html +3 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
# [Latest](https://github.com/browserless/chrome/compare/v2.
|
|
1
|
+
# [Latest](https://github.com/browserless/chrome/compare/v2.12.0...main)
|
|
2
|
+
- Dependency updates.
|
|
3
|
+
|
|
4
|
+
# [v2.12.0](https://github.com/browserless/chrome/compare/v2.11.0...v2.12.0)
|
|
5
|
+
**Potentially Breaking**
|
|
6
|
+
- SDK projects should now use conventional class method properties versus the "fat-arrow" style instance methods.
|
|
7
|
+
|
|
8
|
+
**Updates**
|
|
9
|
+
- Support for multi-version playwright (puppeteer coming soon). Browserless now checks the version in the User-Agent header and loads the appropriate playwright server for it.
|
|
2
10
|
- Dependency updates.
|
|
3
11
|
|
|
4
12
|
# [v2.11.0](https://github.com/browserless/chrome/compare/v2.10.0...v2.11.0)
|
package/bin/scaffold/README.md
CHANGED
|
@@ -175,7 +175,7 @@ export default class HelloWorldRoute extends HTTPRoute {
|
|
|
175
175
|
// Handler is a function, getting the request and response objects, and is where you'll write the
|
|
176
176
|
// core logic behind this route. Use utilities like writeResponse or writeJSONResponse to help
|
|
177
177
|
// return the appropriate response.
|
|
178
|
-
handler
|
|
178
|
+
async handler (_req, res, _logger: Logger): Promise<void> {
|
|
179
179
|
const response: ResponseSchema = 'Hello World!';
|
|
180
180
|
return writeResponse(res, 200, ResponseSchema, contentTypes.text);
|
|
181
181
|
};
|
|
@@ -228,8 +228,9 @@ export default class ChromiumWebSocketRoute extends BrowserWebsocketRoute {
|
|
|
228
228
|
// Routes with a browser type get a browser argument of the Browser instance, otherwise
|
|
229
229
|
// request, socket, and head are the other 3 arguments. Here we pass them through
|
|
230
230
|
// and proxy the request into Chromium to handle.
|
|
231
|
-
handler
|
|
232
|
-
chromium.proxyWebSocket(req, socket, head);
|
|
231
|
+
async handler (req, socket, head, logger, chromium): Promise<void> {
|
|
232
|
+
return chromium.proxyWebSocket(req, socket, head);
|
|
233
|
+
}
|
|
233
234
|
}
|
|
234
235
|
```
|
|
235
236
|
|
|
@@ -284,7 +285,7 @@ import { Config } from '@browserless.io/browserless';
|
|
|
284
285
|
// Your config class must be the default export
|
|
285
286
|
// and you can export the Class or an instance of it.
|
|
286
287
|
export default class MyConfig extends Config {
|
|
287
|
-
public getS3Bucket
|
|
288
|
+
public getS3Bucket(): string {
|
|
288
289
|
// Load from environment variables or default to some other named bucket.
|
|
289
290
|
return process.env.S3_BUCKET ?? 'my-fun-s3-bucket';
|
|
290
291
|
};
|
|
@@ -344,7 +345,7 @@ export default class PDFToS3Route extends BrowserHTTPRoute {
|
|
|
344
345
|
tags = [APITags.browserAPI];
|
|
345
346
|
|
|
346
347
|
// Handler's are where we embed the logic that facilitates this route.
|
|
347
|
-
handler
|
|
348
|
+
async handler (req, res, logger, browser): Promise<void> {
|
|
348
349
|
// Modules like Config are injected via this internal methods.
|
|
349
350
|
// Use them to load core modules within the platform.
|
|
350
351
|
const config = this.config() as MyConfig;
|
|
@@ -22,13 +22,13 @@ export default class HelloWorldHTTPRoute extends HTTPRoute {
|
|
|
22
22
|
method = Methods.get;
|
|
23
23
|
path = '/hello';
|
|
24
24
|
tags = [APITags.management];
|
|
25
|
-
handler
|
|
25
|
+
async handler (
|
|
26
26
|
req: Request,
|
|
27
27
|
res: Response,
|
|
28
28
|
logger: Logger,
|
|
29
|
-
): Promise<void>
|
|
29
|
+
): Promise<void> {
|
|
30
30
|
logger.verbose(`${req.method} /hello was called!`);
|
|
31
31
|
const response: ResponseSchema = 'Hello World!';
|
|
32
32
|
return writeResponse(res, 200, response, contentTypes.text);
|
|
33
|
-
}
|
|
33
|
+
}
|
|
34
34
|
}
|
package/build/browserless.d.ts
CHANGED
|
@@ -36,9 +36,9 @@ export declare class Browserless extends EventEmitter {
|
|
|
36
36
|
token?: Browserless['token'];
|
|
37
37
|
webhooks?: Browserless['webhooks'];
|
|
38
38
|
});
|
|
39
|
-
protected loadPwVersions
|
|
40
|
-
protected saveMetrics
|
|
41
|
-
setMetricsSaveInterval
|
|
39
|
+
protected loadPwVersions(): Promise<void>;
|
|
40
|
+
protected saveMetrics(): Promise<void>;
|
|
41
|
+
setMetricsSaveInterval(interval: number): void;
|
|
42
42
|
protected routeIsDisabled(route: routeInstances): boolean;
|
|
43
43
|
setStaticSDKDir(dir: string): void;
|
|
44
44
|
disableRoutes(...routeNames: string[]): void;
|
package/build/browserless.js
CHANGED
|
@@ -45,11 +45,11 @@ export class Browserless extends EventEmitter {
|
|
|
45
45
|
router ||
|
|
46
46
|
new Router(this.config, this.browserManager, this.limiter, this.Logger);
|
|
47
47
|
}
|
|
48
|
-
|
|
48
|
+
async loadPwVersions() {
|
|
49
49
|
const { playwrightVersions } = JSON.parse((await fs.readFile('package.json')).toString());
|
|
50
50
|
this.config.setPwVersions(playwrightVersions);
|
|
51
|
-
}
|
|
52
|
-
|
|
51
|
+
}
|
|
52
|
+
async saveMetrics() {
|
|
53
53
|
const metricsPath = this.config.getMetricsJSONPath();
|
|
54
54
|
const { cpu, memory } = await this.monitoring.getMachineStats();
|
|
55
55
|
const metrics = await this.metrics.get();
|
|
@@ -76,15 +76,15 @@ export class Browserless extends EventEmitter {
|
|
|
76
76
|
this.logger.info(`Saving metrics to "${metricsPath}"`);
|
|
77
77
|
this.fileSystem.append(metricsPath, JSON.stringify(aggregatedStats), false);
|
|
78
78
|
}
|
|
79
|
-
}
|
|
80
|
-
setMetricsSaveInterval
|
|
79
|
+
}
|
|
80
|
+
setMetricsSaveInterval(interval) {
|
|
81
81
|
if (interval <= 0) {
|
|
82
82
|
return console.warn(`Interval value of "${interval}" must be greater than 1. Ignoring`);
|
|
83
83
|
}
|
|
84
84
|
clearInterval(this.metricsSaveInterval);
|
|
85
85
|
this.metricsSaveInterval = interval;
|
|
86
86
|
this.metricsSaveIntervalID = setInterval(this.saveMetrics, this.metricsSaveInterval);
|
|
87
|
-
}
|
|
87
|
+
}
|
|
88
88
|
routeIsDisabled(route) {
|
|
89
89
|
return this.disabledRouteNames.some((name) => name === route.name);
|
|
90
90
|
}
|
|
@@ -27,16 +27,16 @@ export declare class ChromiumCDP extends EventEmitter {
|
|
|
27
27
|
});
|
|
28
28
|
protected cleanListeners(): void;
|
|
29
29
|
keepUntil(): number;
|
|
30
|
-
getPageId
|
|
31
|
-
protected onTargetCreated
|
|
32
|
-
isRunning
|
|
33
|
-
newPage
|
|
34
|
-
close
|
|
35
|
-
pages
|
|
36
|
-
process
|
|
37
|
-
launch
|
|
38
|
-
wsEndpoint
|
|
39
|
-
publicWSEndpoint
|
|
40
|
-
proxyPageWebSocket
|
|
41
|
-
proxyWebSocket
|
|
30
|
+
getPageId(page: Page): string;
|
|
31
|
+
protected onTargetCreated(target: Target): Promise<void>;
|
|
32
|
+
isRunning(): boolean;
|
|
33
|
+
newPage(): Promise<Page>;
|
|
34
|
+
close(): Promise<void>;
|
|
35
|
+
pages(): Promise<Page[]>;
|
|
36
|
+
process(): import("child_process").ChildProcess | null;
|
|
37
|
+
launch(options?: CDPLaunchOptions): Promise<Browser>;
|
|
38
|
+
wsEndpoint(): string | null;
|
|
39
|
+
publicWSEndpoint(token: string | null): string | null;
|
|
40
|
+
proxyPageWebSocket(req: Request, socket: Duplex, head: Buffer): Promise<void>;
|
|
41
|
+
proxyWebSocket(req: Request, socket: Duplex, head: Buffer): Promise<void>;
|
|
42
42
|
}
|
|
@@ -35,11 +35,11 @@ export class ChromiumCDP extends EventEmitter {
|
|
|
35
35
|
keepUntil() {
|
|
36
36
|
return 0;
|
|
37
37
|
}
|
|
38
|
-
getPageId
|
|
38
|
+
getPageId(page) {
|
|
39
39
|
// @ts-ignore
|
|
40
40
|
return page.target()._targetId;
|
|
41
|
-
}
|
|
42
|
-
|
|
41
|
+
}
|
|
42
|
+
async onTargetCreated(target) {
|
|
43
43
|
if (target.type() === 'page') {
|
|
44
44
|
const page = await target.page().catch((e) => {
|
|
45
45
|
this.logger.error(`Error in ${this.constructor.name} new page ${e}`);
|
|
@@ -83,15 +83,17 @@ export class ChromiumCDP extends EventEmitter {
|
|
|
83
83
|
this.emit('newPage', page);
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
|
-
}
|
|
87
|
-
isRunning
|
|
88
|
-
|
|
86
|
+
}
|
|
87
|
+
isRunning() {
|
|
88
|
+
return this.running;
|
|
89
|
+
}
|
|
90
|
+
async newPage() {
|
|
89
91
|
if (!this.browser) {
|
|
90
92
|
throw new ServerError(`${this.constructor.name} hasn't been launched yet!`);
|
|
91
93
|
}
|
|
92
94
|
return this.browser.newPage();
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
+
}
|
|
96
|
+
async close() {
|
|
95
97
|
if (this.browser) {
|
|
96
98
|
this.logger.info(`Closing ${this.constructor.name} process and all listeners`);
|
|
97
99
|
this.emit('close');
|
|
@@ -102,10 +104,14 @@ export class ChromiumCDP extends EventEmitter {
|
|
|
102
104
|
this.browser = null;
|
|
103
105
|
this.browserWSEndpoint = null;
|
|
104
106
|
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
107
|
+
}
|
|
108
|
+
async pages() {
|
|
109
|
+
return this.browser?.pages() || [];
|
|
110
|
+
}
|
|
111
|
+
process() {
|
|
112
|
+
return this.browser?.process() || null;
|
|
113
|
+
}
|
|
114
|
+
async launch(options = {}) {
|
|
109
115
|
this.port = await getPort();
|
|
110
116
|
this.logger.info(`${this.constructor.name} got open port ${this.port}`);
|
|
111
117
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
@@ -130,14 +136,16 @@ export class ChromiumCDP extends EventEmitter {
|
|
|
130
136
|
: puppeteer.launch.bind(puppeteer);
|
|
131
137
|
this.logger.info(finalOptions, `Launching ${this.constructor.name} Handler`);
|
|
132
138
|
this.browser = (await launch(finalOptions));
|
|
133
|
-
this.browser.on('targetcreated', this.onTargetCreated);
|
|
139
|
+
this.browser.on('targetcreated', this.onTargetCreated.bind(this));
|
|
134
140
|
this.running = true;
|
|
135
141
|
this.browserWSEndpoint = this.browser.wsEndpoint();
|
|
136
142
|
this.logger.info(`${this.constructor.name} is running on ${this.browserWSEndpoint}`);
|
|
137
143
|
return this.browser;
|
|
138
|
-
}
|
|
139
|
-
wsEndpoint
|
|
140
|
-
|
|
144
|
+
}
|
|
145
|
+
wsEndpoint() {
|
|
146
|
+
return this.browserWSEndpoint;
|
|
147
|
+
}
|
|
148
|
+
publicWSEndpoint(token) {
|
|
141
149
|
if (!this.browserWSEndpoint) {
|
|
142
150
|
return null;
|
|
143
151
|
}
|
|
@@ -148,55 +156,59 @@ export class ChromiumCDP extends EventEmitter {
|
|
|
148
156
|
externalURL.searchParams.set('token', token);
|
|
149
157
|
}
|
|
150
158
|
return externalURL.href;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
proxyWebSocket = async (req, socket, head) => new Promise((resolve, reject) => {
|
|
177
|
-
if (!this.browserWSEndpoint) {
|
|
178
|
-
throw new ServerError(`No browserWSEndpoint found, did you launch first?`);
|
|
179
|
-
}
|
|
180
|
-
const close = once(() => {
|
|
181
|
-
this.browser?.off('close', close);
|
|
182
|
-
this.browser?.process()?.off('close', close);
|
|
183
|
-
socket.off('close', close);
|
|
184
|
-
return resolve();
|
|
159
|
+
}
|
|
160
|
+
async proxyPageWebSocket(req, socket, head) {
|
|
161
|
+
return new Promise(async (resolve, reject) => {
|
|
162
|
+
if (!this.browserWSEndpoint || !this.browser) {
|
|
163
|
+
throw new ServerError(`No browserWSEndpoint found, did you launch first?`);
|
|
164
|
+
}
|
|
165
|
+
socket.once('close', resolve);
|
|
166
|
+
this.logger.info(`Proxying ${req.parsed.href} to ${this.constructor.name}`);
|
|
167
|
+
const shouldMakePage = req.parsed.pathname.includes(BLESS_PAGE_IDENTIFIER);
|
|
168
|
+
const page = shouldMakePage ? await this.browser.newPage() : null;
|
|
169
|
+
const pathname = page
|
|
170
|
+
? path.join('/devtools', '/page', this.getPageId(page))
|
|
171
|
+
: req.parsed.pathname;
|
|
172
|
+
const target = new URL(pathname, this.browserWSEndpoint).href;
|
|
173
|
+
req.url = '';
|
|
174
|
+
// Delete headers known to cause issues
|
|
175
|
+
delete req.headers.origin;
|
|
176
|
+
this.proxy.ws(req, socket, head, {
|
|
177
|
+
changeOrigin: true,
|
|
178
|
+
target,
|
|
179
|
+
}, (error) => {
|
|
180
|
+
this.logger.error(`Error proxying session to ${this.constructor.name}: ${error}`);
|
|
181
|
+
this.close();
|
|
182
|
+
return reject(error);
|
|
183
|
+
});
|
|
185
184
|
});
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
this.close
|
|
199
|
-
|
|
185
|
+
}
|
|
186
|
+
async proxyWebSocket(req, socket, head) {
|
|
187
|
+
return new Promise((resolve, reject) => {
|
|
188
|
+
if (!this.browserWSEndpoint) {
|
|
189
|
+
throw new ServerError(`No browserWSEndpoint found, did you launch first?`);
|
|
190
|
+
}
|
|
191
|
+
const close = once(() => {
|
|
192
|
+
this.browser?.off('close', close);
|
|
193
|
+
this.browser?.process()?.off('close', close);
|
|
194
|
+
socket.off('close', close);
|
|
195
|
+
return resolve();
|
|
196
|
+
});
|
|
197
|
+
this.browser?.once('close', close);
|
|
198
|
+
this.browser?.process()?.once('close', close);
|
|
199
|
+
socket.once('close', close);
|
|
200
|
+
this.logger.info(`Proxying ${req.parsed.href} to ${this.constructor.name} ${this.browserWSEndpoint}`);
|
|
201
|
+
req.url = '';
|
|
202
|
+
// Delete headers known to cause issues
|
|
203
|
+
delete req.headers.origin;
|
|
204
|
+
this.proxy.ws(req, socket, head, {
|
|
205
|
+
changeOrigin: true,
|
|
206
|
+
target: this.browserWSEndpoint,
|
|
207
|
+
}, (error) => {
|
|
208
|
+
this.logger.error(`Error proxying session to ${this.constructor.name}: ${error}`);
|
|
209
|
+
this.close();
|
|
210
|
+
return reject(error);
|
|
211
|
+
});
|
|
200
212
|
});
|
|
201
|
-
}
|
|
213
|
+
}
|
|
202
214
|
}
|
|
@@ -23,15 +23,15 @@ export declare class ChromiumPlaywright extends EventEmitter {
|
|
|
23
23
|
});
|
|
24
24
|
protected cleanListeners(): void;
|
|
25
25
|
keepUntil(): number;
|
|
26
|
-
isRunning
|
|
27
|
-
close
|
|
28
|
-
pages
|
|
29
|
-
getPageId
|
|
30
|
-
makeLiveURL
|
|
31
|
-
newPage
|
|
32
|
-
launch
|
|
33
|
-
wsEndpoint
|
|
34
|
-
publicWSEndpoint
|
|
35
|
-
proxyPageWebSocket
|
|
36
|
-
proxyWebSocket
|
|
26
|
+
isRunning(): boolean;
|
|
27
|
+
close(): Promise<void>;
|
|
28
|
+
pages(): Promise<[]>;
|
|
29
|
+
getPageId(): string;
|
|
30
|
+
makeLiveURL(): void;
|
|
31
|
+
newPage(): Promise<Page>;
|
|
32
|
+
launch(options?: BrowserServerOptions, version?: string): Promise<playwright.BrowserServer>;
|
|
33
|
+
wsEndpoint(): string | null;
|
|
34
|
+
publicWSEndpoint(token: string | null): string | null;
|
|
35
|
+
proxyPageWebSocket(): Promise<void>;
|
|
36
|
+
proxyWebSocket(req: Request, socket: Duplex, head: Buffer): Promise<void>;
|
|
37
37
|
}
|
|
@@ -25,8 +25,10 @@ export class ChromiumPlaywright extends EventEmitter {
|
|
|
25
25
|
keepUntil() {
|
|
26
26
|
return 0;
|
|
27
27
|
}
|
|
28
|
-
isRunning
|
|
29
|
-
|
|
28
|
+
isRunning() {
|
|
29
|
+
return this.running;
|
|
30
|
+
}
|
|
31
|
+
async close() {
|
|
30
32
|
if (this.browser) {
|
|
31
33
|
this.logger.info(`Closing ${this.constructor.name} process and all listeners`);
|
|
32
34
|
this.emit('close');
|
|
@@ -36,22 +38,24 @@ export class ChromiumPlaywright extends EventEmitter {
|
|
|
36
38
|
this.browser = null;
|
|
37
39
|
this.browserWSEndpoint = null;
|
|
38
40
|
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
|
|
41
|
+
}
|
|
42
|
+
async pages() {
|
|
43
|
+
return [];
|
|
44
|
+
}
|
|
45
|
+
getPageId() {
|
|
42
46
|
throw new ServerError(`#getPageId is not yet supported with ${this.constructor.name}.`);
|
|
43
|
-
}
|
|
44
|
-
makeLiveURL
|
|
47
|
+
}
|
|
48
|
+
makeLiveURL() {
|
|
45
49
|
throw new ServerError(`Live URLs are not yet supported with ${this.constructor.name}. In the future this will be at "${this.config.getExternalAddress()}"`);
|
|
46
|
-
}
|
|
47
|
-
|
|
50
|
+
}
|
|
51
|
+
async newPage() {
|
|
48
52
|
if (!this.browser || !this.browserWSEndpoint) {
|
|
49
53
|
throw new ServerError(`${this.constructor.name} hasn't been launched yet!`);
|
|
50
54
|
}
|
|
51
55
|
const browser = await playwright.chromium.connect(this.browserWSEndpoint);
|
|
52
56
|
return await browser.newPage();
|
|
53
|
-
}
|
|
54
|
-
|
|
57
|
+
}
|
|
58
|
+
async launch(options = {}, version) {
|
|
55
59
|
this.logger.info(`Launching ${this.constructor.name} Handler`);
|
|
56
60
|
const opts = {
|
|
57
61
|
...options,
|
|
@@ -69,9 +73,11 @@ export class ChromiumPlaywright extends EventEmitter {
|
|
|
69
73
|
this.running = true;
|
|
70
74
|
this.browserWSEndpoint = browserWSEndpoint;
|
|
71
75
|
return this.browser;
|
|
72
|
-
}
|
|
73
|
-
wsEndpoint
|
|
74
|
-
|
|
76
|
+
}
|
|
77
|
+
wsEndpoint() {
|
|
78
|
+
return this.browserWSEndpoint;
|
|
79
|
+
}
|
|
80
|
+
publicWSEndpoint(token) {
|
|
75
81
|
if (!this.browserWSEndpoint) {
|
|
76
82
|
return null;
|
|
77
83
|
}
|
|
@@ -82,26 +88,28 @@ export class ChromiumPlaywright extends EventEmitter {
|
|
|
82
88
|
externalURL.searchParams.set('token', token);
|
|
83
89
|
}
|
|
84
90
|
return externalURL.href;
|
|
85
|
-
}
|
|
86
|
-
|
|
91
|
+
}
|
|
92
|
+
async proxyPageWebSocket() {
|
|
87
93
|
this.logger.warn(`${this.constructor.name} Not yet implemented`);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
94
|
+
}
|
|
95
|
+
async proxyWebSocket(req, socket, head) {
|
|
96
|
+
return new Promise((resolve, reject) => {
|
|
97
|
+
if (!this.browserWSEndpoint) {
|
|
98
|
+
throw new ServerError(`No browserWSEndpoint found, did you launch first?`);
|
|
99
|
+
}
|
|
100
|
+
socket.once('close', resolve);
|
|
101
|
+
this.logger.info(`Proxying ${req.parsed.href} to ${this.constructor.name} ${this.browserWSEndpoint}`);
|
|
102
|
+
// Delete headers known to cause issues
|
|
103
|
+
delete req.headers.origin;
|
|
104
|
+
req.url = '';
|
|
105
|
+
this.proxy.ws(req, socket, head, {
|
|
106
|
+
changeOrigin: true,
|
|
107
|
+
target: this.browserWSEndpoint,
|
|
108
|
+
}, (error) => {
|
|
109
|
+
this.logger.error(`Error proxying session to ${this.constructor.name}: ${error}`);
|
|
110
|
+
this.close();
|
|
111
|
+
return reject(error);
|
|
112
|
+
});
|
|
105
113
|
});
|
|
106
|
-
}
|
|
114
|
+
}
|
|
107
115
|
}
|
|
@@ -22,15 +22,15 @@ export declare class FirefoxPlaywright extends EventEmitter {
|
|
|
22
22
|
});
|
|
23
23
|
protected cleanListeners(): void;
|
|
24
24
|
keepUntil(): number;
|
|
25
|
-
isRunning
|
|
26
|
-
close
|
|
27
|
-
pages
|
|
28
|
-
getPageId
|
|
29
|
-
makeLiveURL
|
|
30
|
-
newPage
|
|
31
|
-
launch
|
|
32
|
-
wsEndpoint
|
|
33
|
-
publicWSEndpoint
|
|
34
|
-
proxyPageWebSocket
|
|
35
|
-
proxyWebSocket
|
|
25
|
+
isRunning(): boolean;
|
|
26
|
+
close(): Promise<void>;
|
|
27
|
+
pages(): Promise<[]>;
|
|
28
|
+
getPageId(): string;
|
|
29
|
+
makeLiveURL(): void;
|
|
30
|
+
newPage(): Promise<Page>;
|
|
31
|
+
launch(options?: BrowserServerOptions, version?: string): Promise<playwright.BrowserServer>;
|
|
32
|
+
wsEndpoint(): string | null;
|
|
33
|
+
publicWSEndpoint(token: string | null): string | null;
|
|
34
|
+
proxyPageWebSocket(): Promise<void>;
|
|
35
|
+
proxyWebSocket(req: Request, socket: Duplex, head: Buffer): Promise<void>;
|
|
36
36
|
}
|
|
@@ -24,8 +24,10 @@ export class FirefoxPlaywright extends EventEmitter {
|
|
|
24
24
|
keepUntil() {
|
|
25
25
|
return 0;
|
|
26
26
|
}
|
|
27
|
-
isRunning
|
|
28
|
-
|
|
27
|
+
isRunning() {
|
|
28
|
+
return this.running;
|
|
29
|
+
}
|
|
30
|
+
async close() {
|
|
29
31
|
if (this.browser) {
|
|
30
32
|
this.logger.trace(`Closing ${this.constructor.name} process and all listeners`);
|
|
31
33
|
this.emit('close');
|
|
@@ -35,18 +37,20 @@ export class FirefoxPlaywright extends EventEmitter {
|
|
|
35
37
|
this.browser = null;
|
|
36
38
|
this.browserWSEndpoint = null;
|
|
37
39
|
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
|
|
40
|
+
}
|
|
41
|
+
async pages() {
|
|
42
|
+
return [];
|
|
43
|
+
}
|
|
44
|
+
getPageId() {
|
|
41
45
|
throw new ServerError(`#getPageId is not yet supported with ${this.constructor.name}.`);
|
|
42
|
-
}
|
|
43
|
-
makeLiveURL
|
|
46
|
+
}
|
|
47
|
+
makeLiveURL() {
|
|
44
48
|
throw new ServerError(`Live URLs are not yet supported with ${this.constructor.name}.`);
|
|
45
|
-
}
|
|
46
|
-
|
|
49
|
+
}
|
|
50
|
+
async newPage() {
|
|
47
51
|
throw new ServerError(`Can't create new page with ${this.constructor.name}`);
|
|
48
|
-
}
|
|
49
|
-
|
|
52
|
+
}
|
|
53
|
+
async launch(options = {}, version) {
|
|
50
54
|
this.logger.info(`Launching ${this.constructor.name} Handler`);
|
|
51
55
|
const opts = {
|
|
52
56
|
...options,
|
|
@@ -63,9 +67,11 @@ export class FirefoxPlaywright extends EventEmitter {
|
|
|
63
67
|
this.browserWSEndpoint = browserWSEndpoint;
|
|
64
68
|
this.running = true;
|
|
65
69
|
return this.browser;
|
|
66
|
-
}
|
|
67
|
-
wsEndpoint
|
|
68
|
-
|
|
70
|
+
}
|
|
71
|
+
wsEndpoint() {
|
|
72
|
+
return this.browserWSEndpoint;
|
|
73
|
+
}
|
|
74
|
+
publicWSEndpoint(token) {
|
|
69
75
|
if (!this.browserWSEndpoint) {
|
|
70
76
|
return null;
|
|
71
77
|
}
|
|
@@ -76,26 +82,28 @@ export class FirefoxPlaywright extends EventEmitter {
|
|
|
76
82
|
externalURL.searchParams.set('token', token);
|
|
77
83
|
}
|
|
78
84
|
return externalURL.href;
|
|
79
|
-
}
|
|
80
|
-
|
|
85
|
+
}
|
|
86
|
+
async proxyPageWebSocket() {
|
|
81
87
|
this.logger.warn(`Not yet implemented in ${this.constructor.name}`);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
88
|
+
}
|
|
89
|
+
async proxyWebSocket(req, socket, head) {
|
|
90
|
+
return new Promise((resolve, reject) => {
|
|
91
|
+
if (!this.browserWSEndpoint) {
|
|
92
|
+
throw new ServerError(`No browserWSEndpoint found, did you launch first?`);
|
|
93
|
+
}
|
|
94
|
+
socket.once('close', resolve);
|
|
95
|
+
this.logger.info(`Proxying ${req.parsed.href} to ${this.constructor.name} ${this.browserWSEndpoint}`);
|
|
96
|
+
// Delete headers known to cause issues
|
|
97
|
+
delete req.headers.origin;
|
|
98
|
+
req.url = '';
|
|
99
|
+
this.proxy.ws(req, socket, head, {
|
|
100
|
+
changeOrigin: true,
|
|
101
|
+
target: this.browserWSEndpoint,
|
|
102
|
+
}, (error) => {
|
|
103
|
+
this.logger.error(`Error proxying session to ${this.constructor.name}: ${error}`);
|
|
104
|
+
this.close();
|
|
105
|
+
return reject(error);
|
|
106
|
+
});
|
|
99
107
|
});
|
|
100
|
-
}
|
|
108
|
+
}
|
|
101
109
|
}
|