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

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 (70) hide show
  1. package/bin/browserless.js +157 -15
  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 +6 -6
  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 +91 -17
  67. package/src/utils.ts +0 -25
  68. package/src/webhooks.ts +2 -2
  69. package/static/docs/swagger.json +9 -9
  70. package/tsconfig.json +7 -10
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,103 @@ 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
+ * Helper function that loads the config module. Defined and injected by
126
+ * browserless after initialization.
127
+ * @returns Config
128
+ */
129
+ getConfig?: () => Browserless['config'];
130
+
131
+ /**
132
+ * Helper function that loads the debug module, useful
133
+ * for logging messages scoped to the routes path. Defined
134
+ * and injected by browserless after initialization.
135
+ * @returns Debug
136
+ */
137
+ getDebug?: () => debug.Debugger;
138
+
139
+ /**
140
+ * Helper function that loads the file-system module
141
+ * for interacting with file-systems. Defined and injected by
142
+ * browserless after initialization.
143
+ * @returns FileSystem
144
+ */
145
+ getFileSystem?: () => Browserless['fileSystem'];
146
+
147
+ /**
148
+ * Helper function that loads the metrics module for
149
+ * collecting and aggregating statistics. Defined and injected by
150
+ * browserless after initialization.
151
+ * @returns Metrics
152
+ */
153
+ getMetrics?: () => Browserless['metrics'];
154
+
155
+ /**
156
+ * Helper function that loads the monitoring module useful
157
+ * for monitoring system health. Defined and injected by
158
+ * browserless after initialization.
159
+ * @returns Monitor
160
+ */
161
+ getMonitoring?: () => Browserless['monitoring'];
162
+
163
+ /**
164
+ * The HTTP path that this route handles, eg '/my-route'
121
165
  */
122
166
  path: HTTPRoutes | WebsocketRoutes | HTTPManagementRoutes | string;
123
167
 
124
168
  /**
125
169
  * The query parameters accepted by the route, defined in
126
- * an object format.
170
+ * an object format. This is auto-generated for you if your
171
+ * route defines and exports a QuerySchema type.
127
172
  */
128
173
  querySchema?: unknown;
129
174
 
130
175
  /**
131
- * The structure of the routes response when successful
176
+ * The structure of the routes response when successful. This
177
+ * is auto-generated for you if your route defines a ResponseSchema
178
+ * type and exports it in your route.
132
179
  */
133
180
  responseSchema?: unknown;
134
181
 
@@ -139,6 +186,11 @@ interface Route {
139
186
  tags: APITags[];
140
187
  }
141
188
 
189
+ /**
190
+ * A primitive HTTP-based route that doesn't require a
191
+ * browser in order to fulfill requests. Used by downstream HTTPRoute
192
+ * and WebSocketRoute
193
+ */
142
194
  interface BasicHTTPRoute extends Route {
143
195
  /**
144
196
  * The allowed Content-Types that this route can read and handle.
@@ -160,6 +212,10 @@ interface BasicHTTPRoute extends Route {
160
212
  method: Methods;
161
213
  }
162
214
 
215
+ /**
216
+ * A HTTP-based route, with a handler, that can fulfill requests without
217
+ * a browser required.
218
+ */
163
219
  export interface HTTPRoute extends BasicHTTPRoute {
164
220
  browser: null;
165
221
 
@@ -169,6 +225,11 @@ export interface HTTPRoute extends BasicHTTPRoute {
169
225
  handler: (req: Request, res: http.ServerResponse) => Promise<unknown>;
170
226
  }
171
227
 
228
+ /**
229
+ * A HTTP-based route, with a handler, that can fulfill requests but
230
+ * requires a browser in order to do so. Handler will then be called
231
+ * with a 3rd argument of the browser class specified.
232
+ */
172
233
  export interface BrowserHTTPRoute extends BasicHTTPRoute {
173
234
  browser: BrowserClasses;
174
235
 
@@ -187,6 +248,10 @@ export interface BrowserHTTPRoute extends BasicHTTPRoute {
187
248
  onNewPage?: undefined;
188
249
  }
189
250
 
251
+ /**
252
+ * A WebSocket-based route, with a handler, that can fulfill requests
253
+ * that do not require a browser in order to operate.
254
+ */
190
255
  export interface WebSocketRoute extends Route {
191
256
  browser: null;
192
257
 
@@ -200,6 +265,11 @@ export interface WebSocketRoute extends Route {
200
265
  ) => Promise<unknown>;
201
266
  }
202
267
 
268
+ /**
269
+ * A WebSocket-based route, with a handler, that can fulfill requests
270
+ * that need a browser. Handler is called with an additional argument of
271
+ * browser (the browser class required to run the route).
272
+ */
203
273
  export interface BrowserWebsocketRoute extends Route {
204
274
  browser: BrowserClasses;
205
275
 
@@ -216,6 +286,10 @@ export interface BrowserWebsocketRoute extends Route {
216
286
  browser: BrowserInstance,
217
287
  ): Promise<unknown>;
218
288
 
289
+ /**
290
+ * An optional function to automatically set up or handle new page
291
+ * creation. Useful for injecting behaviors or other functionality.
292
+ */
219
293
  onNewPage?: (url: URL, page: Page) => Promise<void>;
220
294
  }
221
295