@browserless.io/browserless 2.0.0-beta-1 → 2.0.0-beta-2

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 (69) hide show
  1. package/bin/browserless.js +128 -8
  2. package/build/browserless.d.ts +23 -18
  3. package/build/browserless.js +24 -17
  4. package/build/browsers/cdp-chromium.d.ts +17 -14
  5. package/build/browsers/index.d.ts +27 -10
  6. package/build/browsers/index.js +2 -12
  7. package/build/browsers/playwright-chromium.d.ts +12 -9
  8. package/build/browsers/playwright-firefox.d.ts +12 -9
  9. package/build/browsers/playwright-webkit.d.ts +12 -9
  10. package/build/config.d.ts +31 -31
  11. package/build/exports.d.ts +2 -0
  12. package/build/exports.js +2 -0
  13. package/build/file-system.d.ts +2 -2
  14. package/build/limiter.d.ts +34 -11
  15. package/build/metrics.d.ts +17 -11
  16. package/build/monitoring.d.ts +3 -2
  17. package/build/router.d.ts +28 -0
  18. package/build/router.js +138 -0
  19. package/build/routes/chromium/http/content-post.body.json +8 -8
  20. package/build/routes/chromium/http/download-post.js +1 -1
  21. package/build/routes/chromium/http/function-post.js +1 -1
  22. package/build/routes/chromium/http/pdf-post.body.json +8 -8
  23. package/build/routes/chromium/http/performance.js +1 -1
  24. package/build/routes/chromium/http/scrape-post.body.json +8 -8
  25. package/build/routes/chromium/http/screenshot-post.body.json +8 -8
  26. package/build/routes/chromium/utils/function/client.d.ts +3 -3
  27. package/build/routes/management/http/config-get.js +1 -1
  28. package/build/routes/management/http/metrics-get.js +1 -1
  29. package/build/routes/management/http/metrics-total-get.js +1 -1
  30. package/build/routes/management/http/sessions-get.js +3 -3
  31. package/build/routes/management/http/static-get.js +1 -1
  32. package/build/server.d.ts +22 -27
  33. package/build/server.js +29 -149
  34. package/build/token.d.ts +6 -0
  35. package/build/token.js +21 -0
  36. package/build/types.d.ts +85 -14
  37. package/build/utils.d.ts +1 -2
  38. package/build/utils.js +0 -13
  39. package/build/webhooks.d.ts +2 -2
  40. package/docker/sdk/Dockerfile +2 -6
  41. package/package.json +4 -4
  42. package/src/browserless.ts +44 -32
  43. package/src/browsers/cdp-chromium.ts +13 -13
  44. package/src/browsers/index.ts +9 -24
  45. package/src/browsers/playwright-chromium.ts +9 -9
  46. package/src/browsers/playwright-firefox.ts +9 -9
  47. package/src/browsers/playwright-webkit.ts +9 -9
  48. package/src/config.ts +32 -31
  49. package/src/exports.ts +2 -0
  50. package/src/file-system.ts +2 -2
  51. package/src/limiter.ts +11 -11
  52. package/src/metrics.ts +11 -11
  53. package/src/monitoring.ts +2 -2
  54. package/src/router.ts +234 -0
  55. package/src/routes/chromium/http/download-post.ts +1 -1
  56. package/src/routes/chromium/http/function-post.ts +1 -1
  57. package/src/routes/chromium/http/performance.ts +1 -1
  58. package/src/routes/chromium/utils/function/client.ts +2 -2
  59. package/src/routes/management/http/config-get.ts +1 -1
  60. package/src/routes/management/http/metrics-get.ts +1 -1
  61. package/src/routes/management/http/metrics-total-get.ts +1 -1
  62. package/src/routes/management/http/sessions-get.ts +3 -3
  63. package/src/routes/management/http/static-get.ts +1 -1
  64. package/src/server.ts +43 -238
  65. package/src/token.ts +40 -0
  66. package/src/types.ts +92 -17
  67. package/src/utils.ts +0 -25
  68. package/src/webhooks.ts +2 -2
  69. package/static/docs/swagger.json +9 -9
package/src/server.ts CHANGED
@@ -2,19 +2,15 @@ import * as http from 'http';
2
2
  import * as stream from 'stream';
3
3
  import {
4
4
  BadRequest,
5
- BrowserHTTPRoute,
6
- BrowserManager,
7
- BrowserWebsocketRoute,
8
5
  Config,
9
- HTTPManagementRoutes,
10
6
  HTTPRoute,
11
- Limiter,
12
- Methods,
13
7
  Metrics,
14
8
  NotFound,
15
9
  Request,
16
10
  Response,
11
+ Router,
17
12
  Timeout,
13
+ Token,
18
14
  TooManyRequests,
19
15
  Unauthorized,
20
16
  WebSocketRoute,
@@ -22,8 +18,6 @@ import {
22
18
  contentTypes,
23
19
  convertPathToURL,
24
20
  createLogger,
25
- isAuthorized,
26
- isConnected,
27
21
  queryParamsToObject,
28
22
  readBody,
29
23
  shimLegacyRequests,
@@ -32,7 +26,6 @@ import {
32
26
 
33
27
  // @ts-ignore
34
28
  import Enjoi from 'enjoi';
35
- import micromatch from 'micromatch';
36
29
 
37
30
  export interface HTTPServerOptions {
38
31
  concurrent: number;
@@ -43,26 +36,20 @@ export interface HTTPServerOptions {
43
36
  }
44
37
 
45
38
  export class HTTPServer {
46
- private server: http.Server = http.createServer();
47
- private port: number;
48
- private host?: string;
49
- private log = createLogger('server');
50
- private verbose = createLogger('server:verbose');
39
+ protected server: http.Server = http.createServer();
40
+ protected port: number;
41
+ protected host?: string;
42
+ protected log = createLogger('server');
43
+ protected verbose = createLogger('server:verbose');
51
44
 
52
45
  constructor(
53
- private config: Config,
54
- private metrics: Metrics,
55
- private browserManager: BrowserManager,
56
- private limiter: Limiter,
57
- private httpRoutes: Array<HTTPRoute | BrowserHTTPRoute>,
58
- private webSocketRoutes: Array<WebSocketRoute | BrowserWebsocketRoute>,
46
+ protected config: Config,
47
+ protected metrics: Metrics,
48
+ protected token: Token,
49
+ protected router: Router,
59
50
  ) {
60
51
  this.host = config.getHost();
61
52
  this.port = config.getPort();
62
- this.httpRoutes = httpRoutes.map((r) => this.registerHTTPRoute(r));
63
- this.webSocketRoutes = webSocketRoutes.map((r) =>
64
- this.registerWebSocketRoute(r),
65
- );
66
53
 
67
54
  this.log(
68
55
  `Server instantiated with host "${this.host}" on port "${
@@ -71,33 +58,16 @@ export class HTTPServer {
71
58
  );
72
59
  }
73
60
 
74
- private onQueueFullHTTP = (_req: Request, res: Response) => {
75
- this.log(`Queue is full, sending 429 response`);
76
- return writeResponse(res, 429, 'Too many requests');
77
- };
78
-
79
- private onQueueFullWebSocket = (_req: Request, socket: stream.Duplex) => {
80
- this.log(`Queue is full, sending 429 response`);
81
- return writeResponse(socket, 429, 'Too many requests');
82
- };
83
-
84
- private onHTTPTimeout = (_req: Request, res: Response) => {
85
- this.log(`HTTP job has timedout, sending 429 response`);
86
- return writeResponse(res, 408, 'Request has timed out');
87
- };
88
-
89
- private onWebsocketTimeout = (_req: Request, socket: stream.Duplex) => {
90
- this.log(`Websocket job has timedout, sending 429 response`);
91
- return writeResponse(socket, 408, 'Request has timed out');
92
- };
93
-
94
- private onHTTPUnauthorized = (_req: Request, res: Response) => {
61
+ protected onHTTPUnauthorized = (_req: Request, res: Response) => {
95
62
  this.log(`HTTP request is not properly authorized, responding with 401`);
96
63
  this.metrics.addUnauthorized();
97
64
  return writeResponse(res, 401, 'Bad or missing authentication.');
98
65
  };
99
66
 
100
- private onWebsocketUnauthorized = (_req: Request, socket: stream.Duplex) => {
67
+ protected onWebsocketUnauthorized = (
68
+ _req: Request,
69
+ socket: stream.Duplex,
70
+ ) => {
101
71
  this.log(
102
72
  `Websocket request is not properly authorized, responding with 401`,
103
73
  );
@@ -105,141 +75,6 @@ export class HTTPServer {
105
75
  return writeResponse(socket, 401, 'Bad or missing authentication.');
106
76
  };
107
77
 
108
- private wrapHTTPHandler =
109
- (
110
- route: HTTPRoute | BrowserHTTPRoute,
111
- handler: HTTPRoute['handler'] | BrowserHTTPRoute['handler'],
112
- ) =>
113
- async (req: Request, res: Response) => {
114
- if (!isConnected(res)) {
115
- this.log(`HTTP Request has closed prior to running`);
116
- return Promise.resolve();
117
- }
118
-
119
- if (route.browser) {
120
- const browser = await this.browserManager.getBrowserForRequest(
121
- req,
122
- route,
123
- );
124
-
125
- if (!isConnected(res)) {
126
- this.log(`HTTP Request has closed prior to running`);
127
- this.browserManager.complete(browser);
128
- return Promise.resolve();
129
- }
130
-
131
- if (!browser) {
132
- return writeResponse(res, 500, `Error loading the browser.`);
133
- }
134
-
135
- if (!isConnected(res)) {
136
- this.log(`HTTP Request has closed prior to running`);
137
- return Promise.resolve();
138
- }
139
-
140
- try {
141
- this.verbose(`Running found HTTP handler.`);
142
- return await handler(req, res, browser);
143
- } finally {
144
- this.verbose(`HTTP Request handler has finished.`);
145
- this.browserManager.complete(browser);
146
- }
147
- }
148
-
149
- return (handler as HTTPRoute['handler'])(req, res);
150
- };
151
-
152
- private wrapWebSocketHandler =
153
- (
154
- route: WebSocketRoute | BrowserWebsocketRoute,
155
- handler: WebSocketRoute['handler'] | BrowserWebsocketRoute['handler'],
156
- ) =>
157
- async (req: Request, socket: stream.Duplex, head: Buffer) => {
158
- if (!isConnected(socket)) {
159
- this.log(`WebSocket Request has closed prior to running`);
160
- return Promise.resolve();
161
- }
162
-
163
- if (route.browser) {
164
- const browser = await this.browserManager.getBrowserForRequest(
165
- req,
166
- route,
167
- );
168
-
169
- if (!isConnected(socket)) {
170
- this.log(`WebSocket Request has closed prior to running`);
171
- this.browserManager.complete(browser);
172
- return Promise.resolve();
173
- }
174
-
175
- if (!browser) {
176
- return writeResponse(socket, 500, `Error loading the browser.`);
177
- }
178
-
179
- try {
180
- this.verbose(`Running found WebSocket handler.`);
181
- await handler(req, socket, head, browser);
182
- } finally {
183
- this.verbose(`WebSocket Request handler has finished.`);
184
- this.browserManager.complete(browser);
185
- }
186
- return;
187
- }
188
- return (handler as WebSocketRoute['handler'])(req, socket, head);
189
- };
190
-
191
- private getTimeout(req: Request) {
192
- const timer = req.parsed.searchParams.get('timeout');
193
-
194
- return timer ? +timer : undefined;
195
- }
196
-
197
- private registerHTTPRoute(
198
- route: HTTPRoute | BrowserHTTPRoute,
199
- ): HTTPRoute | BrowserHTTPRoute {
200
- this.verbose(
201
- `Registering HTTP ${route.method.toUpperCase()} ${route.path}`,
202
- );
203
-
204
- route._browserManager = () => this.browserManager;
205
-
206
- const bound = route.handler.bind(route);
207
- const wrapped = this.wrapHTTPHandler(route, bound);
208
-
209
- route.handler = route.concurrency
210
- ? this.limiter.limit(
211
- wrapped,
212
- this.onQueueFullHTTP,
213
- this.onHTTPTimeout,
214
- this.getTimeout,
215
- )
216
- : wrapped;
217
-
218
- return route;
219
- }
220
-
221
- private registerWebSocketRoute(
222
- route: WebSocketRoute | BrowserWebsocketRoute,
223
- ): WebSocketRoute | BrowserWebsocketRoute {
224
- this.verbose(`Registering WebSocket "${route.path}"`);
225
-
226
- route._browserManager = () => this.browserManager;
227
-
228
- const bound = route.handler.bind(route);
229
- const wrapped = this.wrapWebSocketHandler(route, bound);
230
-
231
- route.handler = route.concurrency
232
- ? this.limiter.limit(
233
- wrapped,
234
- this.onQueueFullWebSocket,
235
- this.onWebsocketTimeout,
236
- this.getTimeout,
237
- )
238
- : wrapped;
239
-
240
- return route;
241
- }
242
-
243
78
  public async start(): Promise<void> {
244
79
  this.log(`HTTP Server is starting`);
245
80
 
@@ -268,21 +103,19 @@ export class HTTPServer {
268
103
  public async stop(): Promise<void> {
269
104
  this.log(`HTTP Server is shutting down`);
270
105
  await new Promise((r) => this.server.close(r));
271
- await Promise.all([this.tearDown(), this.browserManager.stop()]);
106
+ await Promise.all([this.tearDown(), this.router.teardown()]);
272
107
  this.log(`HTTP Server shutdown complete`);
273
108
  }
274
109
 
275
- private tearDown() {
110
+ protected tearDown() {
276
111
  this.log(`Tearing down all listeners and internal routes`);
277
112
  this.server && this.server.removeAllListeners();
278
- this.httpRoutes = [];
279
- this.webSocketRoutes = [];
280
113
 
281
114
  // @ts-ignore garbage collect this reference
282
115
  this.server = null;
283
116
  }
284
117
 
285
- private handleRequest = async (
118
+ protected handleRequest = async (
286
119
  request: http.IncomingMessage,
287
120
  res: http.ServerResponse,
288
121
  ) => {
@@ -297,10 +130,6 @@ export class HTTPServer {
297
130
 
298
131
  if (!proceed) return;
299
132
 
300
- const staticHandler = this.httpRoutes.find(
301
- (route) => route.path === HTTPManagementRoutes.static,
302
- ) as HTTPRoute;
303
-
304
133
  if (this.config.getAllowCORS()) {
305
134
  Object.entries(this.config.getCORSHeaders()).forEach(([header, value]) =>
306
135
  res.setHeader(header, value),
@@ -323,36 +152,19 @@ export class HTTPServer {
323
152
  req.parsed.searchParams.delete('body');
324
153
  }
325
154
 
326
- const accepts = (req.headers['accept']?.toLowerCase() || '*/*').split(',');
327
- const contentType = req.headers['content-type']?.toLowerCase() as
328
- | contentTypes
329
- | undefined;
330
-
331
- const found =
332
- this.httpRoutes.find(
333
- (r) =>
334
- micromatch.isMatch(req.parsed.pathname, r.path) &&
335
- r.method === (req.method?.toLocaleLowerCase() as Methods) &&
336
- (accepts.some((a) => a.startsWith('*/*')) ||
337
- r.contentTypes.some((contentType) =>
338
- accepts.includes(contentType),
339
- )) &&
340
- ((!contentType && r.accepts.includes(contentTypes.any)) ||
341
- r.accepts.includes(contentType as contentTypes)),
342
- ) || (req.method?.toLowerCase() === 'get' ? staticHandler : null);
343
-
344
- if (!found) {
155
+ const route = await this.router.getRouteForHTTPRequest(req);
156
+
157
+ if (!route) {
345
158
  this.log(`No matching WebSocket route handler for "${req.parsed.href}"`);
346
159
  writeResponse(res, 404, 'Not Found');
347
160
  return Promise.resolve();
348
161
  }
349
162
 
350
- this.verbose(`Found matching HTTP route handler "${found.path}"`);
163
+ this.verbose(`Found matching HTTP route handler "${route.path}"`);
351
164
 
352
- if (found?.auth) {
165
+ if (route?.auth) {
353
166
  this.verbose(`Authorizing HTTP request to "${request.url}"`);
354
- const tokens = this.config.getToken();
355
- const isPermitted = isAuthorized(req, found, tokens);
167
+ const isPermitted = await this.token.isAuthorized(req, route);
356
168
 
357
169
  if (!isPermitted) {
358
170
  return this.onHTTPUnauthorized(req, res);
@@ -365,8 +177,8 @@ export class HTTPServer {
365
177
 
366
178
  if (
367
179
  ((req.headers['content-type']?.includes(contentTypes.json) ||
368
- (found.accepts.length === 1 &&
369
- found.accepts.includes(contentTypes.json))) &&
180
+ (route.accepts.length === 1 &&
181
+ route.accepts.includes(contentTypes.json))) &&
370
182
  typeof body !== 'object') ||
371
183
  body === null
372
184
  ) {
@@ -374,10 +186,10 @@ export class HTTPServer {
374
186
  return Promise.resolve();
375
187
  }
376
188
 
377
- if (found.querySchema) {
189
+ if (route.querySchema) {
378
190
  this.verbose(`Validating route query-params with QUERY schema`);
379
191
  try {
380
- const schema = Enjoi.schema(found.querySchema);
192
+ const schema = Enjoi.schema(route.querySchema);
381
193
  const valid = schema.validate(req.queryParams, {
382
194
  abortEarly: false,
383
195
  });
@@ -419,10 +231,10 @@ export class HTTPServer {
419
231
  }
420
232
  }
421
233
 
422
- if (found.bodySchema) {
234
+ if (route.bodySchema) {
423
235
  this.verbose(`Validating route payload with BODY schema`);
424
236
  try {
425
- const schema = Enjoi.schema(found.bodySchema);
237
+ const schema = Enjoi.schema(route.bodySchema);
426
238
  const valid = schema.validate(body, { abortEarly: false });
427
239
 
428
240
  if (valid.error) {
@@ -460,9 +272,7 @@ export class HTTPServer {
460
272
  }
461
273
  }
462
274
 
463
- // #wrapHTTPHandler will take care of applying the extra browser
464
- // argument for this to to work properly
465
- return (found as HTTPRoute)
275
+ return (route as HTTPRoute)
466
276
  .handler(req, res)
467
277
  .then(() => {
468
278
  this.verbose('HTTP connection complete');
@@ -488,12 +298,12 @@ export class HTTPServer {
488
298
  return writeResponse(res, 408, e.message);
489
299
  }
490
300
 
491
- this.log(`Error handling request at "${found.path}": ${e}`);
301
+ this.log(`Error handling request at "${route.path}": ${e}`);
492
302
  return writeResponse(res, 500, e.toString());
493
303
  });
494
304
  };
495
305
 
496
- private handleWebSocket = async (
306
+ protected handleWebSocket = async (
497
307
  request: http.IncomingMessage,
498
308
  socket: stream.Duplex,
499
309
  head: Buffer,
@@ -507,29 +317,26 @@ export class HTTPServer {
507
317
 
508
318
  if (!proceed) return;
509
319
 
510
- const { pathname } = req.parsed;
511
320
  req.queryParams = queryParamsToObject(req.parsed.searchParams);
512
321
 
513
- const found = this.webSocketRoutes.find((r) =>
514
- micromatch.isMatch(pathname, r.path),
515
- );
322
+ const route = await this.router.getRouteForWebSocketRequest(req);
516
323
 
517
- if (found) {
518
- this.verbose(`Found matching WebSocket route handler "${found.path}"`);
324
+ if (route) {
325
+ this.verbose(`Found matching WebSocket route handler "${route.path}"`);
519
326
 
520
- if (found?.auth) {
327
+ if (route?.auth) {
521
328
  this.verbose(`Authorizing WebSocket request to "${req.parsed.href}"`);
522
- const isPermitted = isAuthorized(req, found, this.config.getToken());
329
+ const isPermitted = await this.token.isAuthorized(req, route);
523
330
 
524
331
  if (!isPermitted) {
525
332
  return this.onWebsocketUnauthorized(req, socket);
526
333
  }
527
334
  }
528
335
 
529
- if (found.querySchema) {
336
+ if (route.querySchema) {
530
337
  this.verbose(`Validating route query-params with QUERY schema`);
531
338
  try {
532
- const schema = Enjoi.schema(found.querySchema);
339
+ const schema = Enjoi.schema(route.querySchema);
533
340
  const valid = schema.validate(req.queryParams, {
534
341
  abortEarly: false,
535
342
  });
@@ -571,9 +378,7 @@ export class HTTPServer {
571
378
  }
572
379
  }
573
380
 
574
- // #wrapWebSocketHandler will take care of applying the extra browser
575
- // argument for this to to work properly
576
- return (found as WebSocketRoute)
381
+ return (route as WebSocketRoute)
577
382
  .handler(req, socket, head)
578
383
  .then(() => {
579
384
  this.verbose('Websocket connection complete');
@@ -596,7 +401,7 @@ export class HTTPServer {
596
401
  }
597
402
 
598
403
  this.log(
599
- `Error handling request at "${found.path}": ${e}\n${e.stack}`,
404
+ `Error handling request at "${route.path}": ${e}\n${e.stack}`,
600
405
  );
601
406
 
602
407
  return writeResponse(socket, 500, e.message);
package/src/token.ts ADDED
@@ -0,0 +1,40 @@
1
+ import {
2
+ BrowserHTTPRoute,
3
+ BrowserWebsocketRoute,
4
+ Config,
5
+ HTTPRoute,
6
+ Request,
7
+ WebSocketRoute,
8
+ getTokenFromRequest,
9
+ } from '@browserless.io/browserless';
10
+
11
+ export class Token {
12
+ constructor(protected config: Config) {}
13
+
14
+ public isAuthorized = async (
15
+ req: Request,
16
+ route:
17
+ | BrowserHTTPRoute
18
+ | BrowserWebsocketRoute
19
+ | HTTPRoute
20
+ | WebSocketRoute,
21
+ ): Promise<boolean> => {
22
+ const token = this.config.getToken();
23
+
24
+ if (token === null) {
25
+ return true;
26
+ }
27
+
28
+ if (route.auth !== true) {
29
+ return true;
30
+ }
31
+
32
+ const requestToken = getTokenFromRequest(req);
33
+
34
+ if (!requestToken) {
35
+ return false;
36
+ }
37
+
38
+ return (Array.isArray(token) ? token : [token]).includes(requestToken);
39
+ };
40
+ }
package/src/types.ts CHANGED
@@ -2,15 +2,13 @@ import * as http from 'http';
2
2
  import * as stream from 'stream';
3
3
  import {
4
4
  APITags,
5
- BrowserManager,
5
+ Browserless,
6
6
  CDPChromium,
7
7
  Config,
8
- FileSystem,
9
8
  HTTPManagementRoutes,
10
9
  HTTPRoutes,
11
10
  Methods,
12
11
  Metrics,
13
- Monitoring,
14
12
  PlaywrightChromium,
15
13
  PlaywrightFirefox,
16
14
  PlaywrightWebkit,
@@ -81,54 +79,104 @@ export interface BrowserJSON {
81
79
  'WebKit-Version': string;
82
80
  }
83
81
 
82
+ /**
83
+ * The default launch options or a function, accepting
84
+ * the request object, that produces the launch options.
85
+ */
84
86
  type defaultLaunchOptions =
85
87
  | CDPLaunchOptions
86
88
  | BrowserlessLaunch
87
89
  | ((req: Request) => CDPLaunchOptions | BrowserlessLaunch);
88
90
 
89
91
  interface Route {
90
- _browserManager?: () => BrowserManager;
91
- _config?: () => Config;
92
- _debug?: () => debug.Debugger;
93
- _fileSystem?: () => FileSystem;
94
- _metrics?: () => Metrics;
95
- _monitor?: () => Monitoring;
96
-
97
92
  /**
98
- * Whether the route requires a token to access.
93
+ * A boolean, or a function that returns a boolean, on
94
+ * whether the route requires an API token to access.
99
95
  */
100
96
  auth: boolean | ((req: Request) => Promise<boolean>);
101
97
 
102
98
  /**
103
99
  * The schematic of the submitted BODY (typically)
104
- * an object when the route is json-based.
100
+ * an object when the route is json-based. This is generated
101
+ * automatically if your route defines a BodySchema type.
105
102
  */
106
103
  bodySchema?: unknown;
107
104
 
108
105
  /**
109
106
  * Whether the route should be bound by the global
110
- * concurrency limit
107
+ * concurrency limit defined in your configuration.
111
108
  */
112
109
  concurrency: boolean;
113
110
 
114
111
  /**
115
- * Description of the route and what it does
112
+ * Description of the route and what it does. This description
113
+ * is then used in the embedded documentation site.
116
114
  */
117
115
  description: string;
118
116
 
119
117
  /**
120
- * The HTTP path that this route handles
118
+ * Helper function to load the browser-manager instance. Defined
119
+ * and injected by browserless after initialization.
120
+ * @returns BrowserManager
121
+ */
122
+ getBrowserManager?: () => Browserless['browserManager'];
123
+
124
+
125
+ /**
126
+ * Helper function that loads the config module. Defined and injected by
127
+ * browserless after initialization.
128
+ * @returns Config
129
+ */
130
+ getConfig?: () => Browserless['config'];
131
+
132
+ /**
133
+ * Helper function that loads the debug module, useful
134
+ * for logging messages scoped to the routes path. Defined
135
+ * and injected by browserless after initialization.
136
+ * @returns Debug
137
+ */
138
+ getDebug?: () => debug.Debugger;
139
+
140
+ /**
141
+ * Helper function that loads the file-system module
142
+ * for interacting with file-systems. Defined and injected by
143
+ * browserless after initialization.
144
+ * @returns FileSystem
145
+ */
146
+ getFileSystem?: () => Browserless['fileSystem'];
147
+
148
+ /**
149
+ * Helper function that loads the metrics module for
150
+ * collecting and aggregating statistics. Defined and injected by
151
+ * browserless after initialization.
152
+ * @returns Metrics
153
+ */
154
+ getMetrics?: () => Browserless['metrics'];
155
+
156
+ /**
157
+ * Helper function that loads the monitoring module useful
158
+ * for monitoring system health. Defined and injected by
159
+ * browserless after initialization.
160
+ * @returns Monitor
161
+ */
162
+ getMonitoring?: () => Browserless['monitoring'];
163
+
164
+ /**
165
+ * The HTTP path that this route handles, eg '/my-route'
121
166
  */
122
167
  path: HTTPRoutes | WebsocketRoutes | HTTPManagementRoutes | string;
123
168
 
124
169
  /**
125
170
  * The query parameters accepted by the route, defined in
126
- * an object format.
171
+ * an object format. This is auto-generated for you if your
172
+ * route defines and exports a QuerySchema type.
127
173
  */
128
174
  querySchema?: unknown;
129
175
 
130
176
  /**
131
- * The structure of the routes response when successful
177
+ * The structure of the routes response when successful. This
178
+ * is auto-generated for you if your route defines a ResponseSchema
179
+ * type and exports it in your route.
132
180
  */
133
181
  responseSchema?: unknown;
134
182
 
@@ -139,6 +187,11 @@ interface Route {
139
187
  tags: APITags[];
140
188
  }
141
189
 
190
+ /**
191
+ * A primitive HTTP-based route that doesn't require a
192
+ * browser in order to fulfill requests. Used by downstream HTTPRoute
193
+ * and WebSocketRoute
194
+ */
142
195
  interface BasicHTTPRoute extends Route {
143
196
  /**
144
197
  * The allowed Content-Types that this route can read and handle.
@@ -160,6 +213,10 @@ interface BasicHTTPRoute extends Route {
160
213
  method: Methods;
161
214
  }
162
215
 
216
+ /**
217
+ * A HTTP-based route, with a handler, that can fulfill requests without
218
+ * a browser required.
219
+ */
163
220
  export interface HTTPRoute extends BasicHTTPRoute {
164
221
  browser: null;
165
222
 
@@ -169,6 +226,11 @@ export interface HTTPRoute extends BasicHTTPRoute {
169
226
  handler: (req: Request, res: http.ServerResponse) => Promise<unknown>;
170
227
  }
171
228
 
229
+ /**
230
+ * A HTTP-based route, with a handler, that can fulfill requests but
231
+ * requires a browser in order to do so. Handler will then be called
232
+ * with a 3rd argument of the browser class specified.
233
+ */
172
234
  export interface BrowserHTTPRoute extends BasicHTTPRoute {
173
235
  browser: BrowserClasses;
174
236
 
@@ -187,6 +249,10 @@ export interface BrowserHTTPRoute extends BasicHTTPRoute {
187
249
  onNewPage?: undefined;
188
250
  }
189
251
 
252
+ /**
253
+ * A WebSocket-based route, with a handler, that can fulfill requests
254
+ * that do not require a browser in order to operate.
255
+ */
190
256
  export interface WebSocketRoute extends Route {
191
257
  browser: null;
192
258
 
@@ -200,6 +266,11 @@ export interface WebSocketRoute extends Route {
200
266
  ) => Promise<unknown>;
201
267
  }
202
268
 
269
+ /**
270
+ * A WebSocket-based route, with a handler, that can fulfill requests
271
+ * that need a browser. Handler is called with an additional argument of
272
+ * browser (the browser class required to run the route).
273
+ */
203
274
  export interface BrowserWebsocketRoute extends Route {
204
275
  browser: BrowserClasses;
205
276
 
@@ -216,6 +287,10 @@ export interface BrowserWebsocketRoute extends Route {
216
287
  browser: BrowserInstance,
217
288
  ): Promise<unknown>;
218
289
 
290
+ /**
291
+ * An optional function to automatically set up or handle new page
292
+ * creation. Useful for injecting behaviors or other functionality.
293
+ */
219
294
  onNewPage?: (url: URL, page: Page) => Promise<void>;
220
295
  }
221
296