@browserless.io/browserless 2.8.0 → 2.10.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.
Files changed (115) hide show
  1. package/CHANGELOG.md +13 -1
  2. package/README.md +41 -3
  3. package/assets/debugger.png +0 -0
  4. package/bin/scaffold/src/hello-world.http.ts +3 -2
  5. package/build/browserless.d.ts +5 -4
  6. package/build/browserless.js +19 -13
  7. package/build/browsers/chrome.cdp.d.ts +2 -2
  8. package/build/browsers/chrome.cdp.js +2 -2
  9. package/build/browsers/chrome.playwright.d.ts +2 -2
  10. package/build/browsers/chrome.playwright.js +2 -2
  11. package/build/browsers/chromium.cdp.d.ts +4 -4
  12. package/build/browsers/chromium.cdp.js +49 -32
  13. package/build/browsers/chromium.playwright.d.ts +4 -4
  14. package/build/browsers/chromium.playwright.js +14 -13
  15. package/build/browsers/firefox.playwright.d.ts +4 -4
  16. package/build/browsers/firefox.playwright.js +14 -13
  17. package/build/browsers/index.d.ts +24 -8
  18. package/build/browsers/index.js +20 -15
  19. package/build/browsers/webkit.playwright.d.ts +4 -4
  20. package/build/browsers/webkit.playwright.js +14 -13
  21. package/build/config.d.ts +3 -0
  22. package/build/config.js +3 -0
  23. package/build/file-system.d.ts +2 -3
  24. package/build/file-system.js +2 -2
  25. package/build/http.d.ts +1 -0
  26. package/build/http.js +1 -0
  27. package/build/index.js +7 -7
  28. package/build/limiter.d.ts +2 -3
  29. package/build/limiter.js +11 -11
  30. package/build/logger.d.ts +16 -9
  31. package/build/logger.js +32 -16
  32. package/build/monitoring.d.ts +2 -3
  33. package/build/monitoring.js +4 -4
  34. package/build/router.d.ts +1 -3
  35. package/build/router.js +21 -22
  36. package/build/routes/chrome/http/content.post.body.json +8 -8
  37. package/build/routes/chrome/http/pdf.post.body.json +8 -8
  38. package/build/routes/chrome/http/scrape.post.body.json +8 -8
  39. package/build/routes/chrome/http/screenshot.post.body.json +8 -8
  40. package/build/routes/chromium/http/content.post.body.json +8 -8
  41. package/build/routes/chromium/http/pdf.post.body.json +8 -8
  42. package/build/routes/chromium/http/scrape.post.body.json +8 -8
  43. package/build/routes/chromium/http/screenshot.post.body.json +8 -8
  44. package/build/routes/management/http/pressure.get.d.ts +63 -0
  45. package/build/routes/management/http/pressure.get.js +56 -0
  46. package/build/routes/management/http/pressure.get.response.json +76 -0
  47. package/build/routes/management/http/static.get.js +3 -3
  48. package/build/routes/management/tests/management.spec.js +16 -0
  49. package/build/server.d.ts +1 -3
  50. package/build/server.js +33 -30
  51. package/build/shared/content.http.d.ts +1 -1
  52. package/build/shared/content.http.js +4 -1
  53. package/build/shared/download.http.js +9 -9
  54. package/build/shared/function.http.js +2 -2
  55. package/build/shared/json-protocol.http.d.ts +3 -3
  56. package/build/shared/json-protocol.http.js +2 -2
  57. package/build/shared/json-version.http.d.ts +3 -3
  58. package/build/shared/json-version.http.js +2 -2
  59. package/build/shared/pdf.http.d.ts +1 -1
  60. package/build/shared/pdf.http.js +6 -4
  61. package/build/shared/performance.http.js +1 -0
  62. package/build/shared/scrape.http.d.ts +1 -1
  63. package/build/shared/scrape.http.js +4 -1
  64. package/build/shared/screenshot.http.d.ts +1 -1
  65. package/build/shared/screenshot.http.js +4 -1
  66. package/build/shared/utils/function/handler.js +7 -7
  67. package/build/shared/utils/performance/child.js +4 -4
  68. package/build/shared/utils/performance/main.d.ts +1 -1
  69. package/build/shared/utils/performance/main.js +5 -7
  70. package/build/shared/utils/performance/types.d.ts +2 -1
  71. package/build/types.d.ts +10 -1
  72. package/build/types.js +10 -1
  73. package/build/utils.d.ts +1 -1
  74. package/build/utils.js +6 -2
  75. package/package.json +18 -15
  76. package/scripts/install-debugger.js +55 -15
  77. package/src/browserless.ts +25 -12
  78. package/src/browsers/chrome.cdp.ts +2 -5
  79. package/src/browsers/chrome.playwright.ts +2 -5
  80. package/src/browsers/chromium.cdp.ts +84 -35
  81. package/src/browsers/chromium.playwright.ts +26 -13
  82. package/src/browsers/firefox.playwright.ts +28 -13
  83. package/src/browsers/index.ts +24 -16
  84. package/src/browsers/webkit.playwright.ts +28 -13
  85. package/src/config.ts +4 -0
  86. package/src/file-system.ts +2 -7
  87. package/src/http.ts +1 -0
  88. package/src/index.ts +7 -7
  89. package/src/limiter.ts +13 -11
  90. package/src/logger.ts +39 -18
  91. package/src/monitoring.ts +6 -8
  92. package/src/router.ts +20 -20
  93. package/src/routes/management/http/pressure.get.ts +135 -0
  94. package/src/routes/management/http/static.get.ts +3 -5
  95. package/src/routes/management/tests/management.spec.ts +26 -0
  96. package/src/server.ts +43 -30
  97. package/src/shared/content.http.ts +5 -1
  98. package/src/shared/download.http.ts +9 -9
  99. package/src/shared/function.http.ts +2 -2
  100. package/src/shared/json-protocol.http.ts +8 -3
  101. package/src/shared/json-version.http.ts +8 -4
  102. package/src/shared/pdf.http.ts +6 -4
  103. package/src/shared/performance.http.ts +1 -0
  104. package/src/shared/scrape.http.ts +5 -1
  105. package/src/shared/screenshot.http.ts +4 -1
  106. package/src/shared/utils/function/handler.ts +7 -7
  107. package/src/shared/utils/performance/child.ts +4 -4
  108. package/src/shared/utils/performance/main.ts +5 -6
  109. package/src/shared/utils/performance/types.ts +2 -1
  110. package/src/types.ts +9 -0
  111. package/src/utils.ts +7 -2
  112. package/static/docs/swagger.json +138 -10
  113. package/static/docs/swagger.min.json +137 -9
  114. package/static/function/client.js +4290 -5542
  115. package/static/function/index.html +4290 -5542
@@ -1,20 +1,60 @@
1
- import { cp } from 'fs/promises';
2
- import { fileURLToPath } from 'url';
3
- import path from 'path';
1
+ /* global fetch, console, process */
2
+ import { Readable } from 'stream';
3
+ import { existsSync } from 'fs';
4
+ import { join } from 'path';
5
+ import os from 'os';
4
6
 
5
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
7
+ import { deleteAsync } from 'del';
8
+ import gunzip from 'gunzip-maybe';
9
+ import { moveFile } from 'move-file';
10
+ import tar from 'tar-fs';
6
11
 
7
- const from = path.join(
8
- __dirname,
9
- '..',
10
- 'node_modules',
11
- 'browserless-debugger',
12
- 'static',
13
- );
14
- const to = path.join(__dirname, '..', 'static', 'debugger');
12
+ const registryURL = 'https://registry.npmjs.org/@browserless.io/debugger/';
13
+ const tmp = join(os.tmpdir(), 'browserless-debugger');
14
+ const untarDir = join(tmp, 'package', 'static');
15
+ const debuggerDir = join(process.cwd(), 'static', 'debugger');
16
+
17
+ const lastFromArr = (arr) => arr[arr.length - 1];
18
+ const dlAndExtract = (url) =>
19
+ fetch(url).then(
20
+ (response) =>
21
+ new Promise((resolve, reject) => {
22
+ // @ts-ignore
23
+ Readable.fromWeb(response.body)
24
+ .pipe(gunzip())
25
+ .pipe(tar.extract(tmp))
26
+ .on('error', reject)
27
+ .on('finish', resolve);
28
+ }),
29
+ );
30
+
31
+ const getLatestVersion = async () => {
32
+ const response = await fetch(registryURL);
33
+ const json = await response.json();
34
+ const latest = lastFromArr(Object.keys(json.versions));
35
+ return json.versions[latest];
36
+ };
15
37
 
16
38
  (async () => {
17
- await cp(from, to, {
18
- recursive: true,
39
+ if (existsSync(debuggerDir)) {
40
+ await deleteAsync(debuggerDir);
41
+ }
42
+
43
+ const dist = await getLatestVersion()
44
+ .then((version) => version.dist.tarball)
45
+ .catch((error) => {
46
+ console.error(`Couldn't fetch latest debugger version: ${error.message}`);
47
+ process.exit(1);
48
+ });
49
+
50
+ await dlAndExtract(dist).catch((error) => {
51
+ console.error(`Couldn't download debugger: ${error.message}`);
52
+ process.exit(1);
19
53
  });
20
- })();
54
+
55
+ await moveFile(untarDir, debuggerDir);
56
+ await deleteAsync(tmp, { force: true });
57
+ })().catch((error) => {
58
+ console.error(`An error occurred: ${error.message}`);
59
+ process.exit(1);
60
+ });
@@ -23,7 +23,6 @@ import {
23
23
  WebSocketRoute,
24
24
  WebkitPlaywright,
25
25
  availableBrowsers,
26
- createLogger,
27
26
  getRouteFiles,
28
27
  makeExternalURL,
29
28
  printLogo,
@@ -46,7 +45,7 @@ type routeInstances =
46
45
  | BrowserWebsocketRoute;
47
46
 
48
47
  export class Browserless extends EventEmitter {
49
- protected debug: debug.Debugger = createLogger('index');
48
+ protected logger: BlessLogger;
50
49
  protected browserManager: BrowserManager;
51
50
  protected config: Config;
52
51
  protected fileSystem: FileSystem;
@@ -94,6 +93,7 @@ export class Browserless extends EventEmitter {
94
93
  } = {}) {
95
94
  super();
96
95
  this.Logger = LoggerOverride ?? BlessLogger;
96
+ this.logger = new this.Logger('index');
97
97
  this.config = config || new Config();
98
98
  this.metrics = metrics || new Metrics();
99
99
  this.token = token || new Token(this.config);
@@ -129,7 +129,7 @@ export class Browserless extends EventEmitter {
129
129
 
130
130
  this.metrics.reset();
131
131
 
132
- this.debug(
132
+ this.logger.info(
133
133
  `Current period usage: ${JSON.stringify({
134
134
  date: aggregatedStats.date,
135
135
  error: aggregatedStats.error,
@@ -146,7 +146,7 @@ export class Browserless extends EventEmitter {
146
146
  );
147
147
 
148
148
  if (metricsPath) {
149
- this.debug(`Saving metrics to "${metricsPath}"`);
149
+ this.logger.info(`Saving metrics to "${metricsPath}"`);
150
150
  this.fileSystem.append(
151
151
  metricsPath,
152
152
  JSON.stringify(aggregatedStats),
@@ -170,7 +170,7 @@ export class Browserless extends EventEmitter {
170
170
  );
171
171
  };
172
172
 
173
- private routeIsDisabled(route: routeInstances) {
173
+ protected routeIsDisabled(route: routeInstances) {
174
174
  return this.disabledRouteNames.some((name) => name === route.name);
175
175
  }
176
176
 
@@ -230,11 +230,18 @@ export class Browserless extends EventEmitter {
230
230
  const [[internalHttpRouteFiles, internalWsRouteFiles], installedBrowsers] =
231
231
  await Promise.all([getRouteFiles(this.config), availableBrowsers]);
232
232
 
233
+ const hasDebugger = await this.config.hasDebugger();
234
+ const debuggerURL =
235
+ hasDebugger &&
236
+ makeExternalURL(
237
+ this.config.getExternalAddress(),
238
+ `/debugger/?token=${this.config.getToken()}`,
239
+ );
233
240
  const docsLink = makeExternalURL(this.config.getExternalAddress(), '/docs');
234
241
 
235
- this.debug(printLogo(docsLink));
236
- this.debug(`Running as user "${userInfo().username}"`);
237
- this.debug('Starting import of HTTP Routes');
242
+ this.logger.info(printLogo(docsLink, debuggerURL));
243
+ this.logger.info(`Running as user "${userInfo().username}"`);
244
+ this.logger.info('Starting import of HTTP Routes');
238
245
 
239
246
  for (const httpRoute of [
240
247
  ...this.httpRouteFiles,
@@ -265,12 +272,14 @@ export class Browserless extends EventEmitter {
265
272
  this.metrics,
266
273
  this.monitoring,
267
274
  this.staticSDKDir,
275
+ this.limiter,
268
276
  );
269
277
 
270
278
  if (!this.routeIsDisabled(route)) {
271
279
  route.bodySchema = safeParse(bodySchema);
272
280
  route.querySchema = safeParse(querySchema);
273
281
  route.config = () => this.config;
282
+ route.limiter = () => this.limiter;
274
283
  route.metrics = () => this.metrics;
275
284
  route.monitoring = () => this.monitoring;
276
285
  route.fileSystem = () => this.fileSystem;
@@ -281,7 +290,7 @@ export class Browserless extends EventEmitter {
281
290
  }
282
291
  }
283
292
 
284
- this.debug('Starting import of WebSocket Routes');
293
+ this.logger.info('Starting import of WebSocket Routes');
285
294
  for (const wsRoute of [
286
295
  ...this.webSocketRouteFiles,
287
296
  ...internalWsRouteFiles,
@@ -314,11 +323,13 @@ export class Browserless extends EventEmitter {
314
323
  this.metrics,
315
324
  this.monitoring,
316
325
  this.staticSDKDir,
326
+ this.limiter,
317
327
  );
318
328
 
319
329
  if (!this.routeIsDisabled(route)) {
320
330
  route.querySchema = safeParse(querySchema);
321
331
  route.config = () => this.config;
332
+ route.limiter = () => this.limiter;
322
333
  route.metrics = () => this.metrics;
323
334
  route.monitoring = () => this.monitoring;
324
335
  route.fileSystem = () => this.fileSystem;
@@ -349,7 +360,7 @@ export class Browserless extends EventEmitter {
349
360
  .map((r) => r.name);
350
361
 
351
362
  if (duplicateNamedRoutes.length) {
352
- this.debug(
363
+ this.logger.warn(
353
364
  `Found duplicate routing names. Route names must be unique:`,
354
365
  duplicateNamedRoutes,
355
366
  );
@@ -358,7 +369,9 @@ export class Browserless extends EventEmitter {
358
369
  httpRoutes.forEach((r) => this.router.registerHTTPRoute(r));
359
370
  wsRoutes.forEach((r) => this.router.registerWebSocketRoute(r));
360
371
 
361
- this.debug(`Imported and validated all route files, starting up server.`);
372
+ this.logger.info(
373
+ `Imported and validated all route files, starting up server.`,
374
+ );
362
375
 
363
376
  this.server = new HTTPServer(
364
377
  this.config,
@@ -370,7 +383,7 @@ export class Browserless extends EventEmitter {
370
383
  );
371
384
 
372
385
  await this.server.start();
373
- this.debug(`Starting metrics collection.`);
386
+ this.logger.info(`Starting metrics collection.`);
374
387
  this.metricsSaveIntervalID = setInterval(
375
388
  () => this.saveMetrics(),
376
389
  this.metricsSaveInterval,
@@ -1,10 +1,7 @@
1
- import {
2
- chromeExecutablePath,
3
- createLogger,
4
- } from '@browserless.io/browserless';
1
+ import { Logger, chromeExecutablePath } from '@browserless.io/browserless';
5
2
  import { ChromiumCDP } from './chromium.cdp.js';
6
3
 
7
4
  export class ChromeCDP extends ChromiumCDP {
8
5
  protected executablePath = chromeExecutablePath();
9
- protected debug = createLogger('browsers:chrome:cdp');
6
+ protected logger = new Logger('browsers:chrome:cdp');
10
7
  }
@@ -1,10 +1,7 @@
1
- import {
2
- chromeExecutablePath,
3
- createLogger,
4
- } from '@browserless.io/browserless';
1
+ import { Logger, chromeExecutablePath } from '@browserless.io/browserless';
5
2
  import { ChromiumPlaywright } from './chromium.playwright.js';
6
3
 
7
4
  export class ChromePlaywright extends ChromiumPlaywright {
8
5
  protected executablePath = chromeExecutablePath();
9
- protected debug = createLogger('browsers:chrome:playwright');
6
+ protected logger = new Logger('browsers:chrome:playwright');
10
7
  }
@@ -2,9 +2,9 @@ import {
2
2
  BLESS_PAGE_IDENTIFIER,
3
3
  CDPLaunchOptions,
4
4
  Config,
5
+ Logger,
5
6
  Request,
6
7
  ServerError,
7
- createLogger,
8
8
  noop,
9
9
  once,
10
10
  } from '@browserless.io/browserless';
@@ -29,7 +29,7 @@ export class ChromiumCDP extends EventEmitter {
29
29
  protected browser: Browser | null = null;
30
30
  protected browserWSEndpoint: string | null = null;
31
31
  protected port?: number;
32
- protected debug = createLogger('browsers:chromium:cdp');
32
+ protected logger: Logger;
33
33
  protected proxy = httpProxy.createProxyServer();
34
34
  protected executablePath = playwright.chromium.executablePath();
35
35
 
@@ -37,9 +37,11 @@ export class ChromiumCDP extends EventEmitter {
37
37
  blockAds,
38
38
  config,
39
39
  userDataDir,
40
+ logger,
40
41
  }: {
41
42
  blockAds: boolean;
42
43
  config: Config;
44
+ logger: Logger;
43
45
  userDataDir: ChromiumCDP['userDataDir'];
44
46
  }) {
45
47
  super();
@@ -47,7 +49,9 @@ export class ChromiumCDP extends EventEmitter {
47
49
  this.userDataDir = userDataDir;
48
50
  this.config = config;
49
51
  this.blockAds = blockAds;
50
- this.debug(`Starting new browser instance`);
52
+ this.logger = logger;
53
+
54
+ this.logger.info(`Starting new ${this.constructor.name} instance`);
51
55
  }
52
56
 
53
57
  protected cleanListeners() {
@@ -63,31 +67,62 @@ export class ChromiumCDP extends EventEmitter {
63
67
  protected onTargetCreated = async (target: Target) => {
64
68
  if (target.type() === 'page') {
65
69
  const page = await target.page().catch((e) => {
66
- this.debug(`Error in new page ${e}`);
70
+ this.logger.error(`Error in ${this.constructor.name} new page ${e}`);
67
71
  return null;
68
72
  });
69
73
 
70
74
  if (page) {
71
- if (!this.config.getAllowFileProtocol()) {
72
- this.debug(`Setting up file:// protocol request rejection`);
73
- page.on('request', async (request) => {
74
- if (request.url().startsWith('file://')) {
75
- this.debug(`File protocol request found in request, terminating`);
76
- page.close().catch(noop);
77
- this.close();
78
- }
79
- });
80
-
81
- page.on('response', async (response) => {
82
- if (response.url().startsWith('file://')) {
83
- this.debug(
84
- `File protocol request found in response, terminating`,
85
- );
86
- page.close().catch(noop);
87
- this.close();
88
- }
89
- });
90
- }
75
+ this.logger.trace(`Setting up file:// protocol request rejection`);
76
+
77
+ page.on('error', (err) => {
78
+ this.logger.error(err);
79
+ });
80
+
81
+ page.on('pageerror', (err) => {
82
+ this.logger.warn(err);
83
+ });
84
+
85
+ page.on('framenavigated', (frame) => {
86
+ this.logger.trace(`Navigation to ${frame.url()}`);
87
+ });
88
+
89
+ page.on('console', (message) => {
90
+ this.logger.trace(`${message.type()}: ${message.text()}`);
91
+ });
92
+
93
+ page.on('requestfailed', (req) => {
94
+ this.logger.warn(`"${req.failure()?.errorText}": ${req.url()}`);
95
+ });
96
+
97
+ page.on('request', async (request) => {
98
+ this.logger.trace(`${request.method()}: ${request.url()}`);
99
+ if (
100
+ !this.config.getAllowFileProtocol() &&
101
+ request.url().startsWith('file://')
102
+ ) {
103
+ this.logger.error(
104
+ `File protocol request found in request to ${this.constructor.name}, terminating`,
105
+ );
106
+ page.close().catch(noop);
107
+ this.close();
108
+ }
109
+ });
110
+
111
+ page.on('response', async (response) => {
112
+ this.logger.trace(`${response.status()}: ${response.url()}`);
113
+
114
+ if (
115
+ !this.config.getAllowFileProtocol() &&
116
+ response.url().startsWith('file://')
117
+ ) {
118
+ this.logger.error(
119
+ `File protocol request found in response to ${this.constructor.name}, terminating`,
120
+ );
121
+ page.close().catch(noop);
122
+ this.close();
123
+ }
124
+ });
125
+
91
126
  this.emit('newPage', page);
92
127
  }
93
128
  }
@@ -97,7 +132,9 @@ export class ChromiumCDP extends EventEmitter {
97
132
 
98
133
  public newPage = async (): Promise<Page> => {
99
134
  if (!this.browser) {
100
- throw new ServerError(`Browser hasn't been launched yet!`);
135
+ throw new ServerError(
136
+ `${this.constructor.name} hasn't been launched yet!`,
137
+ );
101
138
  }
102
139
 
103
140
  return this.browser.newPage();
@@ -105,7 +142,9 @@ export class ChromiumCDP extends EventEmitter {
105
142
 
106
143
  public close = async (): Promise<void> => {
107
144
  if (this.browser) {
108
- this.debug(`Closing browser process and all listeners`);
145
+ this.logger.info(
146
+ `Closing ${this.constructor.name} process and all listeners`,
147
+ );
109
148
  this.emit('close');
110
149
  this.cleanListeners();
111
150
  this.browser.removeAllListeners();
@@ -122,7 +161,7 @@ export class ChromiumCDP extends EventEmitter {
122
161
 
123
162
  public launch = async (options: CDPLaunchOptions = {}): Promise<Browser> => {
124
163
  this.port = await getPort();
125
- this.debug(`Got open port ${this.port}`);
164
+ this.logger.info(`${this.constructor.name} got open port ${this.port}`);
126
165
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
127
166
  const finalOptions = {
128
167
  ...options,
@@ -157,13 +196,17 @@ export class ChromiumCDP extends EventEmitter {
157
196
  ? puppeteerStealth.launch.bind(puppeteerStealth)
158
197
  : puppeteer.launch.bind(puppeteer);
159
198
 
160
- this.debug(finalOptions, `Launching CDP Handler`);
161
- // @ts-ignore mis-matched types from stealth...
199
+ this.logger.info(
200
+ finalOptions,
201
+ `Launching ${this.constructor.name} Handler`,
202
+ );
162
203
  this.browser = (await launch(finalOptions)) as Browser;
163
204
  this.browser.on('targetcreated', this.onTargetCreated);
164
205
  this.running = true;
165
206
  this.browserWSEndpoint = this.browser.wsEndpoint();
166
- this.debug(`Browser is running on ${this.browserWSEndpoint}`);
207
+ this.logger.info(
208
+ `${this.constructor.name} is running on ${this.browserWSEndpoint}`,
209
+ );
167
210
 
168
211
  return this.browser;
169
212
  };
@@ -199,7 +242,9 @@ export class ChromiumCDP extends EventEmitter {
199
242
  );
200
243
  }
201
244
  socket.once('close', resolve);
202
- this.debug(`Proxying ${req.parsed.href}`);
245
+ this.logger.info(
246
+ `Proxying ${req.parsed.href} to ${this.constructor.name}`,
247
+ );
203
248
 
204
249
  const shouldMakePage = req.parsed.pathname.includes(
205
250
  BLESS_PAGE_IDENTIFIER,
@@ -223,7 +268,9 @@ export class ChromiumCDP extends EventEmitter {
223
268
  target,
224
269
  },
225
270
  (error) => {
226
- this.debug(`Error proxying session: ${error}`);
271
+ this.logger.error(
272
+ `Error proxying session to ${this.constructor.name}: ${error}`,
273
+ );
227
274
  this.close();
228
275
  return reject(error);
229
276
  },
@@ -253,8 +300,8 @@ export class ChromiumCDP extends EventEmitter {
253
300
  this.browser?.process()?.once('close', close);
254
301
  socket.once('close', close);
255
302
 
256
- this.debug(
257
- `Proxying ${req.parsed.href} to browser ${this.browserWSEndpoint}`,
303
+ this.logger.info(
304
+ `Proxying ${req.parsed.href} to ${this.constructor.name} ${this.browserWSEndpoint}`,
258
305
  );
259
306
 
260
307
  req.url = '';
@@ -271,7 +318,9 @@ export class ChromiumCDP extends EventEmitter {
271
318
  target: this.browserWSEndpoint,
272
319
  },
273
320
  (error) => {
274
- this.debug(`Error proxying session: ${error}`);
321
+ this.logger.error(
322
+ `Error proxying session to ${this.constructor.name}: ${error}`,
323
+ );
275
324
  this.close();
276
325
  return reject(error);
277
326
  },
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  BrowserServerOptions,
3
3
  Config,
4
+ Logger,
4
5
  Request,
5
6
  ServerError,
6
- createLogger,
7
7
  } from '@browserless.io/browserless';
8
8
  import playwright, { Page } from 'playwright-core';
9
9
  import { Duplex } from 'stream';
@@ -15,25 +15,28 @@ export class ChromiumPlaywright extends EventEmitter {
15
15
  protected config: Config;
16
16
  protected userDataDir: string | null;
17
17
  protected running = false;
18
+ protected logger: Logger;
18
19
  protected proxy = httpProxy.createProxyServer();
19
20
  protected browser: playwright.BrowserServer | null = null;
20
21
  protected browserWSEndpoint: string | null = null;
21
- protected debug = createLogger('browsers:chromium:playwright');
22
22
  protected executablePath = playwright.chromium.executablePath();
23
23
 
24
24
  constructor({
25
25
  config,
26
26
  userDataDir,
27
+ logger,
27
28
  }: {
28
29
  config: Config;
30
+ logger: Logger;
29
31
  userDataDir: ChromiumPlaywright['userDataDir'];
30
32
  }) {
31
33
  super();
32
34
 
33
35
  this.userDataDir = userDataDir;
34
36
  this.config = config;
37
+ this.logger = logger;
35
38
 
36
- this.debug(`Starting new browser instance`);
39
+ this.logger.info(`Starting new ${this.constructor.name} instance`);
37
40
  }
38
41
 
39
42
  protected cleanListeners() {
@@ -44,7 +47,9 @@ export class ChromiumPlaywright extends EventEmitter {
44
47
 
45
48
  public close = async (): Promise<void> => {
46
49
  if (this.browser) {
47
- this.debug(`Closing browser process and all listeners`);
50
+ this.logger.info(
51
+ `Closing ${this.constructor.name} process and all listeners`,
52
+ );
48
53
  this.emit('close');
49
54
  this.cleanListeners();
50
55
  this.browser.close();
@@ -57,18 +62,22 @@ export class ChromiumPlaywright extends EventEmitter {
57
62
  public pages = async (): Promise<[]> => [];
58
63
 
59
64
  public getPageId = (): string => {
60
- throw new ServerError(`#getPageId is not yet supported with this browser.`);
65
+ throw new ServerError(
66
+ `#getPageId is not yet supported with ${this.constructor.name}.`,
67
+ );
61
68
  };
62
69
 
63
70
  public makeLiveURL = (): void => {
64
71
  throw new ServerError(
65
- `Live URLs are not yet supported with this browser. In the future this will be at "${this.config.getExternalAddress()}"`,
72
+ `Live URLs are not yet supported with ${this.constructor.name}. In the future this will be at "${this.config.getExternalAddress()}"`,
66
73
  );
67
74
  };
68
75
 
69
76
  public newPage = async (): Promise<Page> => {
70
77
  if (!this.browser || !this.browserWSEndpoint) {
71
- throw new ServerError(`Browser hasn't been launched yet!`);
78
+ throw new ServerError(
79
+ `${this.constructor.name} hasn't been launched yet!`,
80
+ );
72
81
  }
73
82
  const browser = await playwright.chromium.connect(this.browserWSEndpoint);
74
83
  return await browser.newPage();
@@ -77,7 +86,7 @@ export class ChromiumPlaywright extends EventEmitter {
77
86
  public launch = async (
78
87
  options: BrowserServerOptions = {},
79
88
  ): Promise<playwright.BrowserServer> => {
80
- this.debug(`Launching Playwright Handler`);
89
+ this.logger.info(`Launching ${this.constructor.name} Handler`);
81
90
 
82
91
  this.browser = await playwright.chromium.launchServer({
83
92
  ...options,
@@ -91,7 +100,9 @@ export class ChromiumPlaywright extends EventEmitter {
91
100
 
92
101
  const browserWSEndpoint = this.browser.wsEndpoint();
93
102
 
94
- this.debug(`Browser is running on ${browserWSEndpoint}`);
103
+ this.logger.info(
104
+ `${this.constructor.name} is running on ${browserWSEndpoint}`,
105
+ );
95
106
  this.running = true;
96
107
  this.browserWSEndpoint = browserWSEndpoint;
97
108
 
@@ -118,7 +129,7 @@ export class ChromiumPlaywright extends EventEmitter {
118
129
  };
119
130
 
120
131
  public proxyPageWebSocket = async () => {
121
- console.warn(`Not yet implemented`);
132
+ this.logger.warn(`${this.constructor.name} Not yet implemented`);
122
133
  };
123
134
 
124
135
  public proxyWebSocket = async (
@@ -134,8 +145,8 @@ export class ChromiumPlaywright extends EventEmitter {
134
145
  }
135
146
  socket.once('close', resolve);
136
147
 
137
- this.debug(
138
- `Proxying ${req.parsed.href} to browser ${this.browserWSEndpoint}`,
148
+ this.logger.info(
149
+ `Proxying ${req.parsed.href} to ${this.constructor.name} ${this.browserWSEndpoint}`,
139
150
  );
140
151
 
141
152
  // Delete headers known to cause issues
@@ -152,7 +163,9 @@ export class ChromiumPlaywright extends EventEmitter {
152
163
  target: this.browserWSEndpoint,
153
164
  },
154
165
  (error) => {
155
- this.debug(`Error proxying session: ${error}`);
166
+ this.logger.error(
167
+ `Error proxying session to ${this.constructor.name}: ${error}`,
168
+ );
156
169
  this.close();
157
170
  return reject(error);
158
171
  },