@browserless.io/browserless 2.0.0-beta-5 → 2.0.0-beta-7

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 (246) hide show
  1. package/LICENSE +2 -0
  2. package/README.md +11 -11
  3. package/bin/browserless.js +169 -11
  4. package/bin/scaffold/README.md +415 -0
  5. package/bin/scaffold/package.json +21 -0
  6. package/bin/scaffold/src/hello-world.http.ts +27 -0
  7. package/bin/scaffold/tsconfig.json +4 -0
  8. package/build/browserless.js +18 -15
  9. package/build/browsers/index.d.ts +2 -18
  10. package/build/browsers/index.js +43 -14
  11. package/build/file-system.d.ts +5 -0
  12. package/build/file-system.js +20 -5
  13. package/build/file-system.spec.d.ts +1 -0
  14. package/build/file-system.spec.js +44 -0
  15. package/build/http.d.ts +3 -3
  16. package/build/http.js +3 -3
  17. package/build/router.js +2 -4
  18. package/build/routes/chromium/http/content-post.body.json +8 -8
  19. package/build/routes/chromium/http/content-post.d.ts +15 -3
  20. package/build/routes/chromium/http/content-post.js +14 -15
  21. package/build/routes/chromium/http/download-post.d.ts +16 -3
  22. package/build/routes/chromium/http/download-post.js +17 -22
  23. package/build/routes/chromium/http/function-post.d.ts +16 -3
  24. package/build/routes/chromium/http/function-post.js +17 -22
  25. package/build/routes/chromium/http/pdf-post.body.json +8 -8
  26. package/build/routes/chromium/http/pdf-post.d.ts +15 -3
  27. package/build/routes/chromium/http/pdf-post.js +19 -15
  28. package/build/routes/chromium/http/performance.d.ts +15 -3
  29. package/build/routes/chromium/http/performance.js +15 -23
  30. package/build/routes/chromium/http/scrape-post.body.json +8 -8
  31. package/build/routes/chromium/http/scrape-post.d.ts +15 -3
  32. package/build/routes/chromium/http/scrape-post.js +15 -16
  33. package/build/routes/chromium/http/screenshot-post.body.json +8 -8
  34. package/build/routes/chromium/http/screenshot-post.d.ts +15 -3
  35. package/build/routes/chromium/http/screenshot-post.js +18 -15
  36. package/build/routes/chromium/tests/websocket.spec.js +20 -1
  37. package/build/routes/chromium/utils/function/handler.js +2 -2
  38. package/build/routes/chromium/ws/browser.d.ts +13 -3
  39. package/build/routes/chromium/ws/browser.js +10 -11
  40. package/build/routes/chromium/ws/cdp-chromium.d.ts +13 -3
  41. package/build/routes/chromium/ws/cdp-chromium.js +10 -11
  42. package/build/routes/chromium/ws/page.d.ts +13 -3
  43. package/build/routes/chromium/ws/page.js +10 -11
  44. package/build/routes/chromium/ws/playwright-chromium.d.ts +13 -3
  45. package/build/routes/chromium/ws/playwright-chromium.js +11 -12
  46. package/build/routes/firefox/ws/playwright-firefox.d.ts +13 -3
  47. package/build/routes/firefox/ws/playwright-firefox.js +11 -12
  48. package/build/routes/management/http/config-get.d.ts +15 -3
  49. package/build/routes/management/http/config-get.js +15 -20
  50. package/build/routes/management/http/metrics-get.d.ts +15 -3
  51. package/build/routes/management/http/metrics-get.js +16 -21
  52. package/build/routes/management/http/metrics-total-get.d.ts +15 -3
  53. package/build/routes/management/http/metrics-total-get.js +16 -21
  54. package/build/routes/management/http/sessions-get.d.ts +15 -3
  55. package/build/routes/management/http/sessions-get.js +16 -20
  56. package/build/routes/management/http/static-get.d.ts +15 -3
  57. package/build/routes/management/http/static-get.js +15 -20
  58. package/build/routes/webkit/ws/playwright-webkit.d.ts +13 -3
  59. package/build/routes/webkit/ws/playwright-webkit.js +11 -12
  60. package/build/server.js +0 -1
  61. package/build/types.d.ts +48 -38
  62. package/build/types.js +135 -0
  63. package/extensions/ublock/1p-filters.html +0 -1
  64. package/extensions/ublock/3p-filters.html +0 -2
  65. package/extensions/ublock/_locales/bg/messages.json +6 -6
  66. package/extensions/ublock/_locales/br_FR/messages.json +14 -14
  67. package/extensions/ublock/_locales/bs/messages.json +8 -8
  68. package/extensions/ublock/_locales/ca/messages.json +1 -1
  69. package/extensions/ublock/_locales/da/messages.json +5 -5
  70. package/extensions/ublock/_locales/fa/messages.json +1 -1
  71. package/extensions/ublock/_locales/fi/messages.json +6 -6
  72. package/extensions/ublock/_locales/hr/messages.json +4 -4
  73. package/extensions/ublock/_locales/nb/messages.json +1 -1
  74. package/extensions/ublock/_locales/no/messages.json +1 -1
  75. package/extensions/ublock/_locales/ro/messages.json +2 -2
  76. package/extensions/ublock/_locales/ru/messages.json +1 -1
  77. package/extensions/ublock/_locales/sk/messages.json +1 -1
  78. package/extensions/ublock/_locales/sv/messages.json +2 -2
  79. package/extensions/ublock/_locales/te/messages.json +17 -17
  80. package/extensions/ublock/_locales/vi/messages.json +12 -12
  81. package/extensions/ublock/_locales/zh_TW/messages.json +13 -13
  82. package/extensions/ublock/assets/assets.json +3 -3
  83. package/extensions/ublock/assets/resources/scriptlets.js +218 -97
  84. package/extensions/ublock/assets/thirdparties/easylist/easylist.txt +3010 -2056
  85. package/extensions/ublock/assets/thirdparties/easylist/easyprivacy.txt +624 -433
  86. package/extensions/ublock/assets/thirdparties/pgl.yoyo.org/as/serverlist +93 -24
  87. package/extensions/ublock/assets/thirdparties/publicsuffix.org/list/effective_tld_names.dat +7 -15
  88. package/extensions/ublock/assets/thirdparties/urlhaus-filter/urlhaus-filter-online.txt +795 -777
  89. package/extensions/ublock/assets/ublock/badware.min.txt +138 -72
  90. package/extensions/ublock/assets/ublock/filters.min.txt +1929 -2735
  91. package/extensions/ublock/assets/ublock/privacy.min.txt +57 -26
  92. package/extensions/ublock/assets/ublock/quick-fixes.min.txt +125 -74
  93. package/extensions/ublock/assets/ublock/unbreak.min.txt +46 -53
  94. package/extensions/ublock/css/codemirror.css +8 -7
  95. package/extensions/ublock/css/dom-inspector.css +40 -0
  96. package/extensions/ublock/css/logger-ui-inspector.css +7 -1
  97. package/extensions/ublock/css/logger-ui.css +12 -5
  98. package/extensions/ublock/css/popup-fenix.css +1 -1
  99. package/extensions/ublock/devtools.html +1 -0
  100. package/extensions/ublock/js/1p-filters.js +4 -3
  101. package/extensions/ublock/js/3p-filters.js +25 -31
  102. package/extensions/ublock/js/about.js +1 -1
  103. package/extensions/ublock/js/advanced-settings.js +1 -1
  104. package/extensions/ublock/js/asset-viewer.js +1 -1
  105. package/extensions/ublock/js/assets.js +74 -44
  106. package/extensions/ublock/js/background.js +9 -3
  107. package/extensions/ublock/js/base64-custom.js +1 -1
  108. package/extensions/ublock/js/benchmarks.js +1 -1
  109. package/extensions/ublock/js/biditrie.js +1 -1
  110. package/extensions/ublock/js/broadcast.js +75 -0
  111. package/extensions/ublock/js/cachestorage.js +68 -45
  112. package/extensions/ublock/js/click2load.js +1 -1
  113. package/extensions/ublock/js/cloud-ui.js +1 -1
  114. package/extensions/ublock/js/code-viewer.js +1 -1
  115. package/extensions/ublock/js/codemirror/search-thread.js +1 -1
  116. package/extensions/ublock/js/codemirror/search.js +1 -1
  117. package/extensions/ublock/js/codemirror/ubo-dynamic-filtering.js +1 -1
  118. package/extensions/ublock/js/codemirror/ubo-static-filtering.js +98 -24
  119. package/extensions/ublock/js/commands.js +1 -1
  120. package/extensions/ublock/js/console.js +1 -1
  121. package/extensions/ublock/js/contentscript-extra.js +1 -1
  122. package/extensions/ublock/js/contentscript.js +1 -3
  123. package/extensions/ublock/js/contextmenu.js +1 -1
  124. package/extensions/ublock/js/cosmetic-filtering.js +4 -4
  125. package/extensions/ublock/js/dashboard-common.js +1 -1
  126. package/extensions/ublock/js/dashboard.js +1 -1
  127. package/extensions/ublock/js/devtools.js +23 -15
  128. package/extensions/ublock/js/diff-updater.js +3 -3
  129. package/extensions/ublock/js/document-blocked.js +1 -1
  130. package/extensions/ublock/js/dom-inspector.js +68 -0
  131. package/extensions/ublock/js/dom.js +1 -1
  132. package/extensions/ublock/js/dyna-rules.js +1 -1
  133. package/extensions/ublock/js/dynamic-net-filtering.js +1 -1
  134. package/extensions/ublock/js/epicker-ui.js +35 -59
  135. package/extensions/ublock/js/fa-icons.js +1 -1
  136. package/extensions/ublock/js/filtering-context.js +1 -1
  137. package/extensions/ublock/js/filtering-engines.js +1 -1
  138. package/extensions/ublock/js/hnswitches.js +1 -1
  139. package/extensions/ublock/js/hntrie.js +1 -1
  140. package/extensions/ublock/js/html-filtering.js +1 -1
  141. package/extensions/ublock/js/httpheader-filtering.js +1 -1
  142. package/extensions/ublock/js/i18n.js +1 -1
  143. package/extensions/ublock/js/is-webrtc-supported.js +1 -1
  144. package/extensions/ublock/js/logger-ui-inspector.js +203 -145
  145. package/extensions/ublock/js/logger-ui.js +21 -5
  146. package/extensions/ublock/js/logger.js +6 -2
  147. package/extensions/ublock/js/lz4.js +2 -2
  148. package/extensions/ublock/js/messaging.js +266 -166
  149. package/extensions/ublock/js/mrucache.js +58 -0
  150. package/extensions/ublock/js/pagestore.js +1 -1
  151. package/extensions/ublock/js/popup-fenix.js +2 -1
  152. package/extensions/ublock/js/redirect-engine.js +1 -1
  153. package/extensions/ublock/js/redirect-resources.js +1 -12
  154. package/extensions/ublock/js/reverselookup-worker.js +1 -1
  155. package/extensions/ublock/js/reverselookup.js +1 -1
  156. package/extensions/ublock/js/scriptlet-filtering-core.js +300 -0
  157. package/extensions/ublock/js/scriptlet-filtering.js +122 -350
  158. package/extensions/ublock/js/scriptlets/cosmetic-logger.js +36 -47
  159. package/extensions/ublock/js/scriptlets/cosmetic-off.js +1 -1
  160. package/extensions/ublock/js/scriptlets/cosmetic-on.js +1 -1
  161. package/extensions/ublock/js/scriptlets/cosmetic-report.js +1 -1
  162. package/extensions/ublock/js/scriptlets/dom-inspector.js +341 -323
  163. package/extensions/ublock/js/scriptlets/dom-survey-elements.js +1 -1
  164. package/extensions/ublock/js/scriptlets/dom-survey-scripts.js +1 -1
  165. package/extensions/ublock/js/scriptlets/epicker.js +80 -89
  166. package/extensions/ublock/js/scriptlets/load-3p-css.js +1 -1
  167. package/extensions/ublock/js/scriptlets/load-large-media-all.js +1 -1
  168. package/extensions/ublock/js/scriptlets/load-large-media-interactive.js +1 -1
  169. package/extensions/ublock/js/scriptlets/noscript-spoof.js +1 -1
  170. package/extensions/ublock/js/scriptlets/should-inject-contentscript.js +1 -1
  171. package/extensions/ublock/js/scriptlets/subscriber.js +1 -1
  172. package/extensions/ublock/js/scriptlets/updater.js +20 -3
  173. package/extensions/ublock/js/settings.js +1 -1
  174. package/extensions/ublock/js/start.js +19 -20
  175. package/extensions/ublock/js/static-dnr-filtering.js +1 -1
  176. package/extensions/ublock/js/static-ext-filtering-db.js +1 -1
  177. package/extensions/ublock/js/static-ext-filtering.js +1 -1
  178. package/extensions/ublock/js/static-filtering-io.js +1 -1
  179. package/extensions/ublock/js/static-filtering-parser.js +5 -3
  180. package/extensions/ublock/js/static-net-filtering.js +57 -37
  181. package/extensions/ublock/js/storage.js +49 -29
  182. package/extensions/ublock/js/support.js +4 -4
  183. package/extensions/ublock/js/tab.js +1 -1
  184. package/extensions/ublock/js/tasks.js +1 -1
  185. package/extensions/ublock/js/text-encode.js +1 -1
  186. package/extensions/ublock/js/text-utils.js +1 -1
  187. package/extensions/ublock/js/theme.js +1 -1
  188. package/extensions/ublock/js/traffic.js +2 -1
  189. package/extensions/ublock/js/ublock.js +15 -11
  190. package/extensions/ublock/js/uri-utils.js +1 -1
  191. package/extensions/ublock/js/url-net-filtering.js +1 -1
  192. package/extensions/ublock/js/utils.js +1 -73
  193. package/extensions/ublock/js/vapi-background-ext.js +1 -1
  194. package/extensions/ublock/js/vapi-background.js +92 -83
  195. package/extensions/ublock/js/vapi-client.js +4 -33
  196. package/extensions/ublock/js/vapi-common.js +16 -30
  197. package/extensions/ublock/js/vapi.js +1 -1
  198. package/extensions/ublock/js/wasm/biditrie.wat +1 -1
  199. package/extensions/ublock/js/wasm/hntrie.wat +1 -1
  200. package/extensions/ublock/js/webext.js +1 -1
  201. package/extensions/ublock/js/whitelist.js +1 -1
  202. package/extensions/ublock/logger-ui.html +2 -2
  203. package/extensions/ublock/manifest.json +1 -1
  204. package/extensions/ublock/support.html +0 -1
  205. package/extensions/ublock/web_accessible_resources/dom-inspector.html +25 -0
  206. package/extensions/ublock/web_accessible_resources/epicker-ui.html +0 -1
  207. package/extensions/ublock/web_accessible_resources/googletagservices_gpt.js +1 -0
  208. package/package.json +7 -19
  209. package/scripts/build-open-api.js +7 -4
  210. package/src/browserless.ts +42 -18
  211. package/src/browsers/index.ts +48 -20
  212. package/src/file-system.spec.ts +58 -0
  213. package/src/file-system.ts +36 -8
  214. package/src/http.ts +3 -3
  215. package/src/router.ts +2 -6
  216. package/src/routes/chromium/http/content-post.ts +13 -16
  217. package/src/routes/chromium/http/download-post.ts +16 -27
  218. package/src/routes/chromium/http/function-post.ts +16 -25
  219. package/src/routes/chromium/http/pdf-post.ts +19 -15
  220. package/src/routes/chromium/http/performance.ts +14 -26
  221. package/src/routes/chromium/http/scrape-post.ts +14 -16
  222. package/src/routes/chromium/http/screenshot-post.ts +18 -15
  223. package/src/routes/chromium/tests/websocket.spec.ts +28 -1
  224. package/src/routes/chromium/utils/function/handler.ts +2 -1
  225. package/src/routes/chromium/ws/browser.ts +10 -12
  226. package/src/routes/chromium/ws/cdp-chromium.ts +10 -12
  227. package/src/routes/chromium/ws/page.ts +10 -12
  228. package/src/routes/chromium/ws/playwright-chromium.ts +10 -12
  229. package/src/routes/firefox/ws/playwright-firefox.ts +10 -12
  230. package/src/routes/management/http/config-get.ts +14 -23
  231. package/src/routes/management/http/metrics-get.ts +15 -24
  232. package/src/routes/management/http/metrics-total-get.ts +15 -26
  233. package/src/routes/management/http/sessions-get.ts +15 -23
  234. package/src/routes/management/http/static-get.ts +14 -22
  235. package/src/routes/webkit/ws/playwright-webkit.ts +10 -12
  236. package/src/server.ts +0 -1
  237. package/src/types.ts +59 -45
  238. package/static/docs/browserless-logo-inline.svg +1 -0
  239. package/static/docs/index.html +27 -0
  240. package/static/docs/swagger.json +33 -33
  241. package/static/function/client.js +626 -78
  242. package/extensions/ublock/js/vapi-client-extra.js +0 -312
  243. package/extensions/ublock/web_accessible_resources/addthis_widget.js +0 -39
  244. package/extensions/ublock/web_accessible_resources/ligatus_angular-tag.js +0 -29
  245. package/extensions/ublock/web_accessible_resources/monkeybroker.js +0 -43
  246. package/extensions/ublock/web_accessible_resources/mxpnl_mixpanel.js +0 -51
@@ -16,6 +16,7 @@ import {
16
16
  bestAttempt,
17
17
  bestAttemptCatch,
18
18
  contentTypes,
19
+ dedent,
19
20
  noop,
20
21
  rejectRequestPattern,
21
22
  rejectResourceTypes,
@@ -61,14 +62,22 @@ export interface QuerySchema extends SystemQueryParameters {
61
62
  */
62
63
  export type ResponseSchema = string;
63
64
 
64
- const route: BrowserHTTPRoute = {
65
- accepts: [contentTypes.json],
66
- auth: true,
67
- browser: CDPChromium,
68
- concurrency: true,
69
- contentTypes: [contentTypes.pdf],
70
- description: `A JSON-based API for getting a PDF binary from either a supplied "url" or "html" payload in your request.`,
71
- handler: async (
65
+ export default class PDFPost extends BrowserHTTPRoute {
66
+ accepts = [contentTypes.json];
67
+ auth = true;
68
+ browser = CDPChromium;
69
+ concurrency = true;
70
+ contentTypes = [contentTypes.pdf];
71
+ description = dedent(`
72
+ A JSON-based API for getting a PDF binary from either a supplied
73
+ "url" or "html" payload in your request. Many options exist for
74
+ injecting cookies, request interceptors, user-agents and waiting for
75
+ selectors, timers and more.
76
+ `);
77
+ method = Methods.post;
78
+ path = HTTPRoutes.pdf;
79
+ tags = [APITags.browserAPI];
80
+ handler = async (
72
81
  req: Request,
73
82
  res: ServerResponse,
74
83
  browser: BrowserInstance,
@@ -225,10 +234,5 @@ const route: BrowserHTTPRoute = {
225
234
  });
226
235
 
227
236
  page.close().catch(noop);
228
- },
229
- method: Methods.post,
230
- path: HTTPRoutes.pdf,
231
- tags: [APITags.browserAPI],
232
- };
233
-
234
- export default route;
237
+ };
238
+ }
@@ -1,6 +1,5 @@
1
1
  import {
2
2
  APITags,
3
- BadRequest,
4
3
  BrowserHTTPRoute,
5
4
  BrowserInstance,
6
5
  CDPChromium,
@@ -8,7 +7,6 @@ import {
8
7
  HTTPRoutes,
9
8
  Methods,
10
9
  Request,
11
- ServerError,
12
10
  SystemQueryParameters,
13
11
  contentTypes,
14
12
  jsonResponse,
@@ -34,27 +32,22 @@ export interface QuerySchema extends SystemQueryParameters {
34
32
  */
35
33
  export type ResponseSchema = object;
36
34
 
37
- const route: BrowserHTTPRoute = {
38
- accepts: [contentTypes.json],
39
- auth: true,
40
- browser: CDPChromium,
41
- concurrency: true,
42
- contentTypes: [contentTypes.json],
43
- description: `Run lighthouse performance audits with a supplied "url" in your JSON payload.`,
44
- handler: async (
35
+ export default class PerformancePost extends BrowserHTTPRoute {
36
+ accepts = [contentTypes.json];
37
+ auth = true;
38
+ browser = CDPChromium;
39
+ concurrency = true;
40
+ contentTypes = [contentTypes.json];
41
+ description = `Run lighthouse performance audits with a supplied "url" in your JSON payload.`;
42
+ method = Methods.post;
43
+ path = HTTPRoutes.performance;
44
+ tags = [APITags.browserAPI];
45
+ handler = async (
45
46
  req: Request,
46
47
  res: ServerResponse,
47
48
  browser: BrowserInstance,
48
49
  ): Promise<void> => {
49
- const { getConfig: getConfig } = route;
50
- if (!req.body) {
51
- throw new BadRequest(`No JSON body present`);
52
- }
53
-
54
- if (!getConfig) {
55
- throw new ServerError(`Couldn't load configuration for timeouts`);
56
- }
57
- const config = getConfig();
50
+ const config = this.config();
58
51
  const response = await main({
59
52
  browser,
60
53
  context: req.body as BodySchema,
@@ -62,10 +55,5 @@ const route: BrowserHTTPRoute = {
62
55
  });
63
56
 
64
57
  return jsonResponse(res, 200, response);
65
- },
66
- method: Methods.post,
67
- path: HTTPRoutes.performance,
68
- tags: [APITags.browserAPI],
69
- };
70
-
71
- export default route;
58
+ };
59
+ }
@@ -198,18 +198,21 @@ const scrape = async (elements: ScrapeElementSelector[]) => {
198
198
  });
199
199
  };
200
200
 
201
- const route: BrowserHTTPRoute = {
202
- accepts: [contentTypes.json],
203
- auth: true,
204
- browser: CDPChromium,
205
- concurrency: true,
206
- contentTypes: [contentTypes.json],
207
- description: dedent(`
201
+ export default class ScrapePost extends BrowserHTTPRoute {
202
+ accepts = [contentTypes.json];
203
+ auth = true;
204
+ browser = CDPChromium;
205
+ concurrency = true;
206
+ contentTypes = [contentTypes.json];
207
+ description = dedent(`
208
208
  A JSON-based API that returns text, html, and meta-data from a given list of selectors.
209
209
  Debugging information is available by sending in the appropriate flags in the "debugOpts"
210
210
  property. Responds with an array of JSON objects.
211
- `),
212
- handler: async (
211
+ `);
212
+ method = Methods.post;
213
+ path = HTTPRoutes.scrape;
214
+ tags = [APITags.browserAPI];
215
+ handler = async (
213
216
  req: Request,
214
217
  res: ServerResponse,
215
218
  browser: BrowserInstance,
@@ -430,10 +433,5 @@ const route: BrowserHTTPRoute = {
430
433
  page.close().catch(noop);
431
434
 
432
435
  return jsonResponse(res, 200, response, false);
433
- },
434
- method: Methods.post,
435
- path: HTTPRoutes.scrape,
436
- tags: [APITags.browserAPI],
437
- };
438
-
439
- export default route;
436
+ };
437
+ }
@@ -16,6 +16,7 @@ import {
16
16
  bestAttempt,
17
17
  bestAttemptCatch,
18
18
  contentTypes,
19
+ dedent,
19
20
  noop,
20
21
  rejectRequestPattern,
21
22
  rejectResourceTypes,
@@ -64,14 +65,21 @@ export interface BodySchema {
64
65
  waitForTimeout?: Parameters<Page['waitForTimeout']>[0];
65
66
  }
66
67
 
67
- const route: BrowserHTTPRoute = {
68
- accepts: [contentTypes.json],
69
- auth: true,
70
- browser: CDPChromium,
71
- concurrency: true,
72
- contentTypes: [contentTypes.png, contentTypes.jpeg, contentTypes.text],
73
- description: `A JSON-based API for getting a screenshot binary from either a supplied "url" or "html" payload in your request.`,
74
- handler: async (
68
+ export default class ScreenshotPost extends BrowserHTTPRoute {
69
+ accepts = [contentTypes.json];
70
+ auth = true;
71
+ browser = CDPChromium;
72
+ concurrency = true;
73
+ contentTypes = [contentTypes.png, contentTypes.jpeg, contentTypes.text];
74
+ description = dedent(`
75
+ A JSON-based API for getting a screenshot binary from either a supplied
76
+ "url" or "html" payload in your request. Many options exist including
77
+ cookies, user-agents, setting timers and network mocks.
78
+ `);
79
+ method = Methods.post;
80
+ path = HTTPRoutes.screenshot;
81
+ tags = [APITags.browserAPI];
82
+ handler = async (
75
83
  req: Request,
76
84
  res: ServerResponse,
77
85
  browser: BrowserInstance,
@@ -253,10 +261,5 @@ const route: BrowserHTTPRoute = {
253
261
  await new Promise((r) => readStream.pipe(res).once('close', r));
254
262
 
255
263
  page.close().catch(noop);
256
- },
257
- method: Methods.post,
258
- path: HTTPRoutes.screenshot,
259
- tags: [APITags.browserAPI],
260
- };
261
-
262
- export default route;
264
+ };
265
+ }
@@ -170,6 +170,33 @@ describe('WebSocket API', function () {
170
170
  expect(await exists(userDataDir)).to.be.false;
171
171
  });
172
172
 
173
+ it('allows specified user-data-dirs', async () => {
174
+ const dataDir = '/tmp/data-dir';
175
+ const config = new Config();
176
+ config.setToken('browserless');
177
+ const metrics = new Metrics();
178
+ await start({ config, metrics });
179
+ const launch = JSON.stringify({
180
+ args: [`--user-data-dir=${dataDir}`],
181
+ });
182
+
183
+ const browser = await puppeteer.connect({
184
+ browserWSEndpoint: `ws://localhost:3000?token=browserless&launch=${launch}`,
185
+ });
186
+
187
+ const [{ userDataDir }] = await fetch(
188
+ 'http://localhost:3000/sessions?token=browserless',
189
+ ).then((r) => r.json());
190
+
191
+ expect(await exists(userDataDir)).to.be.true;
192
+ expect(userDataDir).to.equal(dataDir);
193
+
194
+ await browser.disconnect();
195
+ await sleep(1000);
196
+
197
+ expect(await exists(userDataDir)).to.be.true;
198
+ });
199
+
173
200
  it('creates user-data-dirs with userDataDir options', async () => {
174
201
  const dataDirLocation = '/tmp/browserless-test-dir';
175
202
  const launch = JSON.stringify({
@@ -201,7 +228,7 @@ describe('WebSocket API', function () {
201
228
  it('creates user-data-dirs with CLI flags', async () => {
202
229
  const dataDirLocation = '/tmp/browserless-test-dir';
203
230
  const launch = JSON.stringify({
204
- args: [`--user-data-dir==${dataDirLocation}`],
231
+ args: [`--user-data-dir=${dataDirLocation}`],
205
232
  });
206
233
  const config = new Config();
207
234
  config.setToken('browserless');
@@ -9,6 +9,7 @@ import {
9
9
  contentTypes,
10
10
  convertIfBase64,
11
11
  exists,
12
+ getTokenFromRequest,
12
13
  id,
13
14
  makeExternalURL,
14
15
  mimeTypes,
@@ -66,7 +67,7 @@ export default (
66
67
  const context = JSON.stringify(rawContext);
67
68
  const code = convertIfBase64(rawCode);
68
69
  const browserWSEndpoint = browser.publicWSEndpoint(
69
- req.parsed.searchParams.get('token') ?? '',
70
+ getTokenFromRequest(req) ?? '',
70
71
  );
71
72
 
72
73
  if (!browserWSEndpoint) {
@@ -13,19 +13,17 @@ export interface QuerySchema extends SystemQueryParameters {
13
13
  launch?: CDPLaunchOptions | string;
14
14
  }
15
15
 
16
- const route: BrowserWebsocketRoute = {
17
- auth: true,
18
- browser: CDPChromium,
19
- concurrency: false,
20
- description: `Connect to an already-running Chromium with a library like puppeteer, or others, that work over chrome-devtools-protocol.`,
21
- handler: async (
16
+ export default class CDPExistingBrowser extends BrowserWebsocketRoute {
17
+ auth = true;
18
+ browser = CDPChromium;
19
+ concurrency = false;
20
+ description = `Connect to an already-running Chromium with a library like puppeteer, or others, that work over chrome-devtools-protocol.`;
21
+ path = WebsocketRoutes.browser;
22
+ tags = [APITags.browserWS];
23
+ handler = async (
22
24
  req: Request,
23
25
  socket: Duplex,
24
26
  head: Buffer,
25
27
  chrome: CDPChromium,
26
- ): Promise<void> => chrome.proxyWebSocket(req, socket, head),
27
- path: WebsocketRoutes.browser,
28
- tags: [APITags.browserWS],
29
- };
30
-
31
- export default route;
28
+ ): Promise<void> => chrome.proxyWebSocket(req, socket, head);
29
+ }
@@ -13,19 +13,17 @@ export interface QuerySchema extends SystemQueryParameters {
13
13
  launch?: CDPLaunchOptions | string;
14
14
  }
15
15
 
16
- const route: BrowserWebsocketRoute = {
17
- auth: true,
18
- browser: CDPChromium,
19
- concurrency: true,
20
- description: `Launch and connect to Chromium with a library like puppeteer or others that work over chrome-devtools-protocol.`,
21
- handler: async (
16
+ export default class CDPChromiumRoute extends BrowserWebsocketRoute {
17
+ auth = true;
18
+ browser = CDPChromium;
19
+ concurrency = true;
20
+ description = `Launch and connect to Chromium with a library like puppeteer or others that work over chrome-devtools-protocol.`;
21
+ path = WebsocketRoutes['/'];
22
+ tags = [APITags.browserWS];
23
+ handler = async (
22
24
  req: Request,
23
25
  socket: Duplex,
24
26
  head: Buffer,
25
27
  chrome: CDPChromium,
26
- ): Promise<void> => chrome.proxyWebSocket(req, socket, head),
27
- path: WebsocketRoutes['/'],
28
- tags: [APITags.browserWS],
29
- };
30
-
31
- export default route;
28
+ ): Promise<void> => chrome.proxyWebSocket(req, socket, head);
29
+ }
@@ -13,19 +13,17 @@ export interface QuerySchema extends SystemQueryParameters {
13
13
  launch?: CDPLaunchOptions | string;
14
14
  }
15
15
 
16
- const route: BrowserWebsocketRoute = {
17
- auth: true,
18
- browser: CDPChromium,
19
- concurrency: false,
20
- description: `Connect to Chromium with a library like chrome-remote-interface or others that work over JSON chrome-devtools-protocol.`,
21
- handler: async (
16
+ export default class PageWebSocketRoute extends BrowserWebsocketRoute {
17
+ auth = true;
18
+ browser = CDPChromium;
19
+ concurrency = false;
20
+ description = `Connect to Chromium with a library like chrome-remote-interface or others that work over JSON chrome-devtools-protocol.`;
21
+ path = WebsocketRoutes.page;
22
+ tags = [APITags.browserWS];
23
+ handler = async (
22
24
  req: Request,
23
25
  socket: Duplex,
24
26
  head: Buffer,
25
27
  chrome: CDPChromium,
26
- ): Promise<void> => chrome.proxyPageWebSocket(req, socket, head),
27
- path: WebsocketRoutes.page,
28
- tags: [APITags.browserWS],
29
- };
30
-
31
- export default route;
28
+ ): Promise<void> => chrome.proxyPageWebSocket(req, socket, head);
29
+ }
@@ -14,12 +14,14 @@ export interface QuerySchema extends SystemQueryParameters {
14
14
  launch?: BrowserServerOptions | string;
15
15
  }
16
16
 
17
- const route: BrowserWebsocketRoute = {
18
- auth: true,
19
- browser: PlaywrightChromium,
20
- concurrency: true,
21
- description: `Connect to Chromium with any playwright-compliant library.`,
22
- handler: async (
17
+ export default class PlaywrightChromiumRoute extends BrowserWebsocketRoute {
18
+ auth = true;
19
+ browser = PlaywrightChromium;
20
+ concurrency = true;
21
+ description = `Connect to Chromium with any playwright style library.`;
22
+ path = WebsocketRoutes.playwrightChromium;
23
+ tags = [APITags.browserWS];
24
+ handler = async (
23
25
  req: Request,
24
26
  socket: Duplex,
25
27
  head: Buffer,
@@ -36,9 +38,5 @@ const route: BrowserWebsocketRoute = {
36
38
  }
37
39
 
38
40
  return browser.proxyWebSocket(req, socket, head);
39
- },
40
- path: WebsocketRoutes.playwrightChromium,
41
- tags: [APITags.browserWS],
42
- };
43
-
44
- export default route;
41
+ };
42
+ }
@@ -14,12 +14,14 @@ export interface QuerySchema extends SystemQueryParameters {
14
14
  launch?: BrowserServerOptions | string;
15
15
  }
16
16
 
17
- const route: BrowserWebsocketRoute = {
18
- auth: true,
19
- browser: PlaywrightFirefox,
20
- concurrency: true,
21
- description: `Connect to Firefox with any playwright-compliant library.`,
22
- handler: async (
17
+ export default class PlayWrightFirefoxRoute extends BrowserWebsocketRoute {
18
+ auth = true;
19
+ browser = PlaywrightFirefox;
20
+ concurrency = true;
21
+ description = `Connect to Firefox with any playwright-compliant library.`;
22
+ path = WebsocketRoutes.playwrightFirefox;
23
+ tags = [APITags.browserWS];
24
+ handler = async (
23
25
  req: Request,
24
26
  socket: Duplex,
25
27
  head: Buffer,
@@ -36,9 +38,5 @@ const route: BrowserWebsocketRoute = {
36
38
  }
37
39
 
38
40
  return browser.proxyWebSocket(req, socket, head);
39
- },
40
- path: WebsocketRoutes.playwrightFirefox,
41
- tags: [APITags.browserWS],
42
- };
43
-
44
- export default route;
41
+ };
42
+ }
@@ -4,7 +4,6 @@ import {
4
4
  HTTPRoute,
5
5
  Methods,
6
6
  Request,
7
- ServerError,
8
7
  contentTypes,
9
8
  jsonResponse,
10
9
  } from '@browserless.io/browserless';
@@ -33,21 +32,18 @@ export interface ResponseSchema {
33
32
  token: string | null;
34
33
  }
35
34
 
36
- const route: HTTPRoute = {
37
- accepts: [contentTypes.any],
38
- auth: true,
39
- browser: null,
40
- concurrency: false,
41
- contentTypes: [contentTypes.json],
42
- description: `Returns a JSON payload of the current system configuration.`,
43
- handler: async (_req: Request, res: ServerResponse): Promise<void> => {
44
- const { getConfig: getConfig } = route;
45
-
46
- if (!getConfig) {
47
- throw new ServerError(`Couldn't locate the config object`);
48
- }
49
-
50
- const config = getConfig();
35
+ export default class ConfigGetRoute extends HTTPRoute {
36
+ accepts = [contentTypes.any];
37
+ auth = true;
38
+ browser = null;
39
+ concurrency = false;
40
+ contentTypes = [contentTypes.json];
41
+ description = `Returns a JSON payload of the current system configuration.`;
42
+ method = Methods.get;
43
+ path = HTTPManagementRoutes.config;
44
+ tags = [APITags.management];
45
+ handler = async (_req: Request, res: ServerResponse): Promise<void> => {
46
+ const config = this.config();
51
47
 
52
48
  const response: ResponseSchema = {
53
49
  allowCORS: config.getAllowCORS(),
@@ -73,10 +69,5 @@ const route: HTTPRoute = {
73
69
  };
74
70
 
75
71
  return jsonResponse(res, 200, response);
76
- },
77
- method: Methods.get,
78
- path: HTTPManagementRoutes.config,
79
- tags: [APITags.management],
80
- };
81
-
82
- export default route;
72
+ };
73
+ }
@@ -5,7 +5,6 @@ import {
5
5
  IBrowserlessStats,
6
6
  Methods,
7
7
  Request,
8
- ServerError,
9
8
  contentTypes,
10
9
  writeResponse,
11
10
  } from '@browserless.io/browserless';
@@ -13,31 +12,23 @@ import { ServerResponse } from 'http';
13
12
 
14
13
  export type ResponseSchema = Array<IBrowserlessStats>;
15
14
 
16
- const route: HTTPRoute = {
17
- accepts: [contentTypes.any],
18
- auth: true,
19
- browser: null,
20
- concurrency: false,
21
- contentTypes: [contentTypes.json],
22
- description: `Gets total metric details from the time the server started.`,
23
- handler: async (_req: Request, res: ServerResponse): Promise<void> => {
24
- const { getFileSystem: _fileSystem, getConfig: _config } = route;
25
-
26
- if (!_fileSystem || !_config) {
27
- throw new ServerError(`Couldn't locate the file-system or config module`);
28
- }
29
-
30
- const fileSystem = _fileSystem();
31
- const config = _config();
15
+ export default class MetricsGetRoute extends HTTPRoute {
16
+ accepts = [contentTypes.any];
17
+ auth = true;
18
+ browser = null;
19
+ concurrency = false;
20
+ contentTypes = [contentTypes.json];
21
+ description = `Gets total metric details from the time the server started.`;
22
+ method = Methods.get;
23
+ path = HTTPManagementRoutes.metrics;
24
+ tags = [APITags.management];
25
+ handler = async (_req: Request, res: ServerResponse): Promise<void> => {
26
+ const fileSystem = this.fileSystem();
27
+ const config = this.config();
32
28
 
33
29
  const stats = await fileSystem.read(config.getMetricsJSONPath());
34
30
  const response = `[${stats.join(',')}]`;
35
31
 
36
32
  return writeResponse(res, 200, response, contentTypes.json);
37
- },
38
- method: Methods.get,
39
- path: HTTPManagementRoutes.metrics,
40
- tags: [APITags.management],
41
- };
42
-
43
- export default route;
33
+ };
34
+ }
@@ -5,7 +5,6 @@ import {
5
5
  IBrowserlessMetricTotals,
6
6
  Methods,
7
7
  Request,
8
- ServerError,
9
8
  contentTypes,
10
9
  writeResponse,
11
10
  } from '@browserless.io/browserless';
@@ -15,28 +14,23 @@ export type ResponseSchema = IBrowserlessMetricTotals;
15
14
 
16
15
  const fiveMinuteIntervalsInAMonth = 8640;
17
16
 
18
- const route: HTTPRoute = {
19
- accepts: [contentTypes.any],
20
- auth: true,
21
- browser: null,
22
- concurrency: false,
23
- contentTypes: [contentTypes.json],
24
- description: `Gets total metric details summed from the time the server started.`,
25
- handler: async (_req: Request, res: ServerResponse): Promise<void> => {
26
- const { getFileSystem: _fileSystem, getConfig: _config } = route;
27
-
28
- if (!_fileSystem || !_config) {
29
- throw new ServerError(`Couldn't locate the file-system or config module`);
30
- }
31
-
32
- const fileSystem = _fileSystem();
33
- const config = _config();
34
-
17
+ export default class MetricsTotalGetRoute extends HTTPRoute {
18
+ accepts = [contentTypes.any];
19
+ auth = true;
20
+ browser = null;
21
+ concurrency = false;
22
+ contentTypes = [contentTypes.json];
23
+ description = `Gets total metric details summed from the time the server started.`;
24
+ method = Methods.get;
25
+ path = HTTPManagementRoutes.metricsTotal;
26
+ tags = [APITags.management];
27
+ handler = async (_req: Request, res: ServerResponse): Promise<void> => {
28
+ const fileSystem = this.fileSystem();
29
+ const config = this.config();
35
30
  const metrics = (await fileSystem.read(config.getMetricsJSONPath())).map(
36
31
  (m) => JSON.parse(m),
37
32
  );
38
33
  const availableMetrics = metrics.length;
39
-
40
34
  const totals: IBrowserlessMetricTotals = metrics.reduce(
41
35
  (accum, metric) => ({
42
36
  error: accum.error + metric.error,
@@ -80,10 +74,5 @@ const route: HTTPRoute = {
80
74
  );
81
75
 
82
76
  return writeResponse(res, 200, JSON.stringify(totals), contentTypes.json);
83
- },
84
- method: Methods.get,
85
- path: HTTPManagementRoutes.metricsTotal,
86
- tags: [APITags.management],
87
- };
88
-
89
- export default route;
77
+ };
78
+ }
@@ -1,6 +1,5 @@
1
1
  import {
2
2
  APITags,
3
- BadRequest,
4
3
  BrowserlessSessionJSON,
5
4
  HTTPManagementRoutes,
6
5
  HTTPRoute,
@@ -13,27 +12,20 @@ import { ServerResponse } from 'http';
13
12
 
14
13
  export type ResponseSchema = BrowserlessSessionJSON[];
15
14
 
16
- const route: HTTPRoute = {
17
- accepts: [contentTypes.any],
18
- auth: true,
19
- browser: null,
20
- concurrency: false,
21
- contentTypes: [contentTypes.json],
22
- description: `Lists all currently running sessions and relevant meta-data excluding potentially open pages.`,
23
- handler: async (_req: Request, res: ServerResponse): Promise<void> => {
24
- const { getBrowserManager: browserManager } = route;
25
-
26
- if (!browserManager) {
27
- throw new BadRequest(`Couldn't load browsers running`);
28
- }
29
-
30
- const response: ResponseSchema = await browserManager().getAllSessions();
15
+ export default class SessionsGetRoute extends HTTPRoute {
16
+ accepts = [contentTypes.any];
17
+ auth = true;
18
+ browser = null;
19
+ concurrency = false;
20
+ contentTypes = [contentTypes.json];
21
+ description = `Lists all currently running sessions and relevant meta-data excluding potentially open pages.`;
22
+ method = Methods.get;
23
+ path = HTTPManagementRoutes.sessions;
24
+ tags = [APITags.management];
25
+ handler = async (_req: Request, res: ServerResponse): Promise<void> => {
26
+ const browserManager = this.browserManager();
27
+ const response: ResponseSchema = await browserManager.getAllSessions();
31
28
 
32
29
  return jsonResponse(res, 200, response);
33
- },
34
- method: Methods.get,
35
- path: HTTPManagementRoutes.sessions,
36
- tags: [APITags.management],
37
- };
38
-
39
- export default route;
30
+ };
31
+ }