@browserless.io/browserless 2.12.0-beta-4 → 2.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -1
- package/bin/scaffold/README.md +6 -5
- package/bin/scaffold/src/hello-world.http.ts +3 -3
- package/build/browserless.d.ts +3 -3
- package/build/browserless.js +6 -6
- package/build/browsers/chromium.cdp.d.ts +12 -12
- package/build/browsers/chromium.cdp.js +77 -65
- package/build/browsers/chromium.playwright.d.ts +11 -11
- package/build/browsers/chromium.playwright.js +42 -34
- package/build/browsers/firefox.playwright.d.ts +11 -11
- package/build/browsers/firefox.playwright.js +42 -34
- package/build/browsers/index.d.ts +14 -14
- package/build/browsers/index.js +27 -25
- package/build/browsers/webkit.playwright.d.ts +11 -11
- package/build/browsers/webkit.playwright.js +43 -35
- package/build/config.d.ts +65 -63
- package/build/config.js +162 -102
- package/build/file-system.d.ts +4 -4
- package/build/file-system.js +8 -8
- package/build/hooks.d.ts +2 -2
- package/build/hooks.js +4 -4
- package/build/limiter.d.ts +4 -4
- package/build/limiter.js +10 -10
- package/build/logger.d.ts +6 -6
- package/build/logger.js +12 -12
- package/build/metrics.d.ts +12 -12
- package/build/metrics.js +23 -23
- package/build/monitoring.d.ts +4 -4
- package/build/monitoring.js +8 -8
- package/build/router.d.ts +8 -8
- package/build/router.js +74 -70
- package/build/routes/chrome/http/pdf.post.body.json +8 -8
- package/build/routes/chrome/http/scrape.post.body.json +8 -8
- package/build/routes/chrome/http/screenshot.post.body.json +8 -8
- package/build/routes/chromium/http/content.post.body.json +8 -8
- package/build/routes/chromium/http/pdf.post.body.json +8 -8
- package/build/routes/chromium/http/scrape.post.body.json +8 -8
- package/build/routes/chromium/http/screenshot.post.body.json +8 -8
- package/build/routes/firefox/ws/playwright.d.ts +1 -1
- package/build/routes/firefox/ws/playwright.js +2 -2
- package/build/routes/management/http/active.get.d.ts +1 -1
- package/build/routes/management/http/active.get.js +3 -1
- package/build/routes/management/http/config.get.d.ts +1 -1
- package/build/routes/management/http/config.get.js +2 -2
- package/build/routes/management/http/metrics-total.get.d.ts +1 -1
- package/build/routes/management/http/metrics-total.get.js +2 -2
- package/build/routes/management/http/metrics.get.d.ts +1 -1
- package/build/routes/management/http/metrics.get.js +2 -2
- package/build/routes/management/http/pressure.get.d.ts +1 -1
- package/build/routes/management/http/pressure.get.js +2 -2
- package/build/routes/management/http/sessions.get.d.ts +1 -1
- package/build/routes/management/http/sessions.get.js +2 -2
- package/build/routes/management/http/static.get.d.ts +1 -1
- package/build/routes/management/http/static.get.js +2 -2
- package/build/routes/webkit/ws/playwright.d.ts +1 -1
- package/build/routes/webkit/ws/playwright.js +2 -2
- package/build/server.d.ts +5 -5
- package/build/server.js +11 -11
- package/build/shared/browser.ws.d.ts +1 -1
- package/build/shared/browser.ws.js +3 -1
- package/build/shared/chromium.playwright.ws.d.ts +1 -1
- package/build/shared/chromium.playwright.ws.js +2 -2
- package/build/shared/chromium.ws.d.ts +1 -1
- package/build/shared/chromium.ws.js +3 -1
- package/build/shared/content.http.d.ts +1 -1
- package/build/shared/content.http.js +2 -2
- package/build/shared/download.http.d.ts +1 -1
- package/build/shared/download.http.js +60 -58
- package/build/shared/function.http.d.ts +1 -1
- package/build/shared/function.http.js +2 -2
- package/build/shared/json-list.http.d.ts +1 -1
- package/build/shared/json-list.http.js +2 -2
- package/build/shared/json-new.http.d.ts +1 -1
- package/build/shared/json-new.http.js +2 -2
- package/build/shared/json-protocol.http.d.ts +1 -1
- package/build/shared/json-protocol.http.js +2 -2
- package/build/shared/json-version.http.d.ts +1 -1
- package/build/shared/json-version.http.js +2 -2
- package/build/shared/page.ws.d.ts +1 -1
- package/build/shared/page.ws.js +3 -1
- package/build/shared/pdf.http.d.ts +1 -1
- package/build/shared/pdf.http.js +2 -2
- package/build/shared/performance.http.d.ts +1 -1
- package/build/shared/performance.http.js +2 -2
- package/build/shared/scrape.http.d.ts +1 -1
- package/build/shared/scrape.http.js +2 -2
- package/build/shared/screenshot.http.d.ts +1 -1
- package/build/shared/screenshot.http.js +2 -2
- package/build/shared/utils/function/client.d.ts +1 -1
- package/build/shared/utils/function/client.js +3 -1
- package/build/shim.d.ts +1 -1
- package/build/shim.js +2 -2
- package/build/token.d.ts +3 -3
- package/build/token.js +6 -6
- package/build/types.d.ts +4 -4
- package/build/webhooks.d.ts +2 -2
- package/build/webhooks.js +4 -4
- package/package.json +3 -3
- package/src/browserless.ts +6 -6
- package/src/browsers/chromium.cdp.ts +33 -23
- package/src/browsers/chromium.playwright.ts +28 -21
- package/src/browsers/firefox.playwright.ts +28 -21
- package/src/browsers/index.ts +32 -29
- package/src/browsers/webkit.playwright.ts +29 -22
- package/src/config.ts +166 -104
- package/src/file-system.ts +9 -9
- package/src/hooks.ts +4 -4
- package/src/limiter.ts +12 -12
- package/src/logger.ts +12 -12
- package/src/metrics.ts +23 -23
- package/src/monitoring.ts +9 -9
- package/src/router.ts +31 -31
- package/src/routes/firefox/ws/playwright.ts +3 -3
- package/src/routes/management/http/active.get.ts +3 -2
- package/src/routes/management/http/config.get.ts +2 -2
- package/src/routes/management/http/metrics-total.get.ts +2 -2
- package/src/routes/management/http/metrics.get.ts +2 -2
- package/src/routes/management/http/pressure.get.ts +2 -2
- package/src/routes/management/http/sessions.get.ts +2 -2
- package/src/routes/management/http/static.get.ts +3 -3
- package/src/routes/webkit/ws/playwright.ts +3 -3
- package/src/server.ts +14 -16
- package/src/shared/browser.ws.ts +4 -2
- package/src/shared/chromium.playwright.ws.ts +3 -3
- package/src/shared/chromium.ws.ts +4 -2
- package/src/shared/content.http.ts +3 -3
- package/src/shared/download.http.ts +4 -3
- package/src/shared/function.http.ts +3 -3
- package/src/shared/json-list.http.ts +2 -2
- package/src/shared/json-new.http.ts +2 -2
- package/src/shared/json-protocol.http.ts +2 -6
- package/src/shared/json-version.http.ts +2 -6
- package/src/shared/page.ws.ts +4 -2
- package/src/shared/pdf.http.ts +3 -3
- package/src/shared/performance.http.ts +3 -3
- package/src/shared/scrape.http.ts +3 -3
- package/src/shared/screenshot.http.ts +3 -3
- package/src/shared/utils/function/client.ts +3 -1
- package/src/shim.ts +2 -2
- package/src/token.ts +7 -7
- package/src/types.ts +7 -7
- package/src/webhooks.ts +4 -4
- package/static/docs/swagger.json +2 -2
- package/static/docs/swagger.min.json +1 -1
- package/static/function/client.js +3 -1
- package/static/function/index.html +3 -1
package/src/metrics.ts
CHANGED
|
@@ -14,41 +14,41 @@ export class Metrics extends EventEmitter {
|
|
|
14
14
|
protected unhealthy = 0;
|
|
15
15
|
protected error = 0;
|
|
16
16
|
|
|
17
|
-
addSuccessful
|
|
17
|
+
addSuccessful(sessionTime: number): number {
|
|
18
18
|
--this.running;
|
|
19
19
|
this.sessionTimes.push(sessionTime);
|
|
20
20
|
return ++this.successful;
|
|
21
|
-
}
|
|
21
|
+
}
|
|
22
22
|
|
|
23
|
-
addTimedout
|
|
23
|
+
addTimedout(sessionTime: number): number {
|
|
24
24
|
--this.running;
|
|
25
25
|
this.sessionTimes.push(sessionTime);
|
|
26
26
|
return ++this.timedout;
|
|
27
|
-
}
|
|
27
|
+
}
|
|
28
28
|
|
|
29
|
-
addError
|
|
29
|
+
addError(sessionTime: number): number {
|
|
30
30
|
--this.running;
|
|
31
31
|
this.sessionTimes.push(sessionTime);
|
|
32
32
|
return ++this.error;
|
|
33
|
-
}
|
|
33
|
+
}
|
|
34
34
|
|
|
35
|
-
addQueued
|
|
35
|
+
addQueued(): number {
|
|
36
36
|
return ++this.queued;
|
|
37
|
-
}
|
|
37
|
+
}
|
|
38
38
|
|
|
39
|
-
addRejected
|
|
39
|
+
addRejected(): number {
|
|
40
40
|
return ++this.rejected;
|
|
41
|
-
}
|
|
41
|
+
}
|
|
42
42
|
|
|
43
|
-
addUnhealthy
|
|
43
|
+
addUnhealthy(): number {
|
|
44
44
|
return ++this.unhealthy;
|
|
45
|
-
}
|
|
45
|
+
}
|
|
46
46
|
|
|
47
|
-
addUnauthorized
|
|
47
|
+
addUnauthorized(): number {
|
|
48
48
|
return ++this.unauthorized;
|
|
49
|
-
}
|
|
49
|
+
}
|
|
50
50
|
|
|
51
|
-
addRunning
|
|
51
|
+
addRunning(): number {
|
|
52
52
|
++this.running;
|
|
53
53
|
|
|
54
54
|
if (this.concurrent < this.running) {
|
|
@@ -56,9 +56,9 @@ export class Metrics extends EventEmitter {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
return this.running;
|
|
59
|
-
}
|
|
59
|
+
}
|
|
60
60
|
|
|
61
|
-
public get
|
|
61
|
+
public get(): Omit<IBrowserlessStats, 'cpu' | 'memory'> {
|
|
62
62
|
const currentStat = {
|
|
63
63
|
error: this.error,
|
|
64
64
|
maxConcurrent: this.concurrent,
|
|
@@ -77,9 +77,9 @@ export class Metrics extends EventEmitter {
|
|
|
77
77
|
...this.calculateStats(currentStat.sessionTimes),
|
|
78
78
|
date: Date.now(),
|
|
79
79
|
};
|
|
80
|
-
}
|
|
80
|
+
}
|
|
81
81
|
|
|
82
|
-
public reset
|
|
82
|
+
public reset() {
|
|
83
83
|
this.successful = 0;
|
|
84
84
|
this.error = 0;
|
|
85
85
|
this.queued = 0;
|
|
@@ -90,7 +90,7 @@ export class Metrics extends EventEmitter {
|
|
|
90
90
|
this.running = 0;
|
|
91
91
|
this.unhealthy = 0;
|
|
92
92
|
this.sessionTimes = [];
|
|
93
|
-
}
|
|
93
|
+
}
|
|
94
94
|
|
|
95
95
|
protected calculateStats(sessionTimes: number[]) {
|
|
96
96
|
return {
|
|
@@ -112,12 +112,12 @@ export class Metrics extends EventEmitter {
|
|
|
112
112
|
* Implement any browserless-core-specific shutdown logic here.
|
|
113
113
|
* Calls the empty-SDK stop method for downstream implementations.
|
|
114
114
|
*/
|
|
115
|
-
public
|
|
115
|
+
public async shutdown() {
|
|
116
116
|
await this.stop();
|
|
117
|
-
}
|
|
117
|
+
}
|
|
118
118
|
|
|
119
119
|
/**
|
|
120
120
|
* Left blank for downstream SDK modules to optionally implement.
|
|
121
121
|
*/
|
|
122
|
-
public stop
|
|
122
|
+
public stop() {}
|
|
123
123
|
}
|
package/src/monitoring.ts
CHANGED
|
@@ -8,7 +8,7 @@ export class Monitoring extends EventEmitter {
|
|
|
8
8
|
super();
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
public
|
|
11
|
+
public async getMachineStats(): Promise<IResourceLoad> {
|
|
12
12
|
const [cpuLoad, memLoad] = await Promise.all([
|
|
13
13
|
si.currentLoad(),
|
|
14
14
|
si.mem(),
|
|
@@ -24,14 +24,14 @@ export class Monitoring extends EventEmitter {
|
|
|
24
24
|
cpu,
|
|
25
25
|
memory,
|
|
26
26
|
};
|
|
27
|
-
}
|
|
27
|
+
}
|
|
28
28
|
|
|
29
|
-
public
|
|
29
|
+
public async overloaded(): Promise<{
|
|
30
30
|
cpuInt: number | null;
|
|
31
31
|
cpuOverloaded: boolean;
|
|
32
32
|
memoryInt: number | null;
|
|
33
33
|
memoryOverloaded: boolean;
|
|
34
|
-
}>
|
|
34
|
+
}> {
|
|
35
35
|
const { cpu, memory } = await this.getMachineStats();
|
|
36
36
|
const cpuInt = cpu && Math.ceil(cpu * 100);
|
|
37
37
|
const memoryInt = memory && Math.ceil(memory * 100);
|
|
@@ -50,18 +50,18 @@ export class Monitoring extends EventEmitter {
|
|
|
50
50
|
memoryInt,
|
|
51
51
|
memoryOverloaded,
|
|
52
52
|
};
|
|
53
|
-
}
|
|
53
|
+
}
|
|
54
54
|
|
|
55
55
|
/**
|
|
56
56
|
* Implement any browserless-core-specific shutdown logic here.
|
|
57
57
|
* Calls the empty-SDK stop method for downstream implementations.
|
|
58
58
|
*/
|
|
59
|
-
public
|
|
60
|
-
await this.stop();
|
|
61
|
-
}
|
|
59
|
+
public async shutdown() {
|
|
60
|
+
return await this.stop();
|
|
61
|
+
}
|
|
62
62
|
|
|
63
63
|
/**
|
|
64
64
|
* Left blank for downstream SDK modules to optionally implement.
|
|
65
65
|
*/
|
|
66
|
-
public stop
|
|
66
|
+
public stop() {}
|
|
67
67
|
}
|
package/src/router.ts
CHANGED
|
@@ -40,32 +40,31 @@ export class Router extends EventEmitter {
|
|
|
40
40
|
return timer ? +timer : undefined;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
protected onQueueFullHTTP
|
|
43
|
+
protected onQueueFullHTTP(_req: Request, res: Response) {
|
|
44
44
|
this.log.warn(`Queue is full, sending 429 response`);
|
|
45
45
|
return writeResponse(res, 429, 'Too many requests');
|
|
46
|
-
}
|
|
46
|
+
}
|
|
47
47
|
|
|
48
|
-
protected onQueueFullWebSocket
|
|
48
|
+
protected onQueueFullWebSocket(_req: Request, socket: stream.Duplex) {
|
|
49
49
|
this.log.warn(`Queue is full, sending 429 response`);
|
|
50
50
|
return writeResponse(socket, 429, 'Too many requests');
|
|
51
|
-
}
|
|
51
|
+
}
|
|
52
52
|
|
|
53
|
-
protected onHTTPTimeout
|
|
53
|
+
protected onHTTPTimeout(_req: Request, res: Response) {
|
|
54
54
|
this.log.error(`HTTP job has timedout, sending 429 response`);
|
|
55
55
|
return writeResponse(res, 408, 'Request has timed out');
|
|
56
|
-
}
|
|
56
|
+
}
|
|
57
57
|
|
|
58
|
-
protected onWebsocketTimeout
|
|
58
|
+
protected onWebsocketTimeout(_req: Request, socket: stream.Duplex) {
|
|
59
59
|
this.log.error(`Websocket job has timedout, sending 429 response`);
|
|
60
60
|
return writeResponse(socket, 408, 'Request has timed out');
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
protected wrapHTTPHandler
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
) =>
|
|
68
|
-
async (req: Request, res: Response) => {
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
protected wrapHTTPHandler(
|
|
64
|
+
route: HTTPRoute | BrowserHTTPRoute,
|
|
65
|
+
handler: HTTPRoute['handler'] | BrowserHTTPRoute['handler'],
|
|
66
|
+
) {
|
|
67
|
+
return async (req: Request, res: Response) => {
|
|
69
68
|
if (!isConnected(res)) {
|
|
70
69
|
this.log.warn(`HTTP Request has closed prior to running`);
|
|
71
70
|
return Promise.resolve();
|
|
@@ -110,13 +109,13 @@ export class Router extends EventEmitter {
|
|
|
110
109
|
|
|
111
110
|
return (handler as HTTPRoute['handler'])(req, res, logger);
|
|
112
111
|
};
|
|
112
|
+
}
|
|
113
113
|
|
|
114
|
-
protected wrapWebSocketHandler
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
) =>
|
|
119
|
-
async (req: Request, socket: stream.Duplex, head: Buffer) => {
|
|
114
|
+
protected wrapWebSocketHandler(
|
|
115
|
+
route: WebSocketRoute | BrowserWebsocketRoute,
|
|
116
|
+
handler: WebSocketRoute['handler'] | BrowserWebsocketRoute['handler'],
|
|
117
|
+
) {
|
|
118
|
+
return async (req: Request, socket: stream.Duplex, head: Buffer) => {
|
|
120
119
|
if (!isConnected(socket)) {
|
|
121
120
|
this.log.warn(`WebSocket Request has closed prior to running`);
|
|
122
121
|
return Promise.resolve();
|
|
@@ -150,6 +149,7 @@ export class Router extends EventEmitter {
|
|
|
150
149
|
}
|
|
151
150
|
return (handler as WebSocketRoute['handler'])(req, socket, head, logger);
|
|
152
151
|
};
|
|
152
|
+
}
|
|
153
153
|
|
|
154
154
|
public registerHTTPRoute(
|
|
155
155
|
route: HTTPRoute | BrowserHTTPRoute,
|
|
@@ -164,9 +164,9 @@ export class Router extends EventEmitter {
|
|
|
164
164
|
route.handler = route.concurrency
|
|
165
165
|
? this.limiter.limit(
|
|
166
166
|
wrapped,
|
|
167
|
-
this.onQueueFullHTTP,
|
|
168
|
-
this.onHTTPTimeout,
|
|
169
|
-
this.getTimeout,
|
|
167
|
+
this.onQueueFullHTTP.bind(this),
|
|
168
|
+
this.onHTTPTimeout.bind(this),
|
|
169
|
+
this.getTimeout.bind(this),
|
|
170
170
|
)
|
|
171
171
|
: wrapped;
|
|
172
172
|
route.path = Array.isArray(route.path) ? route.path : [route.path];
|
|
@@ -194,9 +194,9 @@ export class Router extends EventEmitter {
|
|
|
194
194
|
route.handler = route.concurrency
|
|
195
195
|
? this.limiter.limit(
|
|
196
196
|
wrapped,
|
|
197
|
-
this.onQueueFullWebSocket,
|
|
198
|
-
this.onWebsocketTimeout,
|
|
199
|
-
this.getTimeout,
|
|
197
|
+
this.onQueueFullWebSocket.bind(this),
|
|
198
|
+
this.onWebsocketTimeout.bind(this),
|
|
199
|
+
this.getTimeout.bind(this),
|
|
200
200
|
)
|
|
201
201
|
: wrapped;
|
|
202
202
|
route.path = Array.isArray(route.path) ? route.path : [route.path];
|
|
@@ -256,14 +256,14 @@ export class Router extends EventEmitter {
|
|
|
256
256
|
* Implement any browserless-core-specific shutdown logic here.
|
|
257
257
|
* Calls the empty-SDK stop method for downstream implementations.
|
|
258
258
|
*/
|
|
259
|
-
public
|
|
259
|
+
public async shutdown() {
|
|
260
260
|
this.httpRoutes = [];
|
|
261
261
|
this.webSocketRoutes = [];
|
|
262
|
-
await this.stop();
|
|
263
|
-
}
|
|
262
|
+
return await this.stop();
|
|
263
|
+
}
|
|
264
264
|
|
|
265
265
|
/**
|
|
266
266
|
* Left blank for downstream SDK modules to optionally implement.
|
|
267
267
|
*/
|
|
268
|
-
public stop
|
|
268
|
+
public stop() {}
|
|
269
269
|
}
|
|
@@ -26,13 +26,13 @@ export default class FirefoxPlaywrightWebSocketRoute extends BrowserWebsocketRou
|
|
|
26
26
|
description = `Connect to Firefox with any playwright-compliant library.`;
|
|
27
27
|
path = [WebsocketRoutes.playwrightFirefox, WebsocketRoutes.firefoxPlaywright];
|
|
28
28
|
tags = [APITags.browserWS];
|
|
29
|
-
|
|
29
|
+
async handler(
|
|
30
30
|
req: Request,
|
|
31
31
|
socket: Duplex,
|
|
32
32
|
head: Buffer,
|
|
33
33
|
_logger: Logger,
|
|
34
34
|
browser: FirefoxPlaywright,
|
|
35
|
-
): Promise<void>
|
|
35
|
+
): Promise<void> {
|
|
36
36
|
const isPlaywright = req.headers['user-agent']
|
|
37
37
|
?.toLowerCase()
|
|
38
38
|
.includes('playwright');
|
|
@@ -44,5 +44,5 @@ export default class FirefoxPlaywrightWebSocketRoute extends BrowserWebsocketRou
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
return browser.proxyWebSocket(req, socket, head);
|
|
47
|
-
}
|
|
47
|
+
}
|
|
48
48
|
}
|
|
@@ -25,6 +25,7 @@ export default class ActiveGetRoute extends HTTPRoute {
|
|
|
25
25
|
method = Methods.get;
|
|
26
26
|
path = HTTPManagementRoutes.active;
|
|
27
27
|
tags = [APITags.management];
|
|
28
|
-
|
|
29
|
-
writeResponse(res, 204, '', contentTypes.text);
|
|
28
|
+
async handler(_req: Request, res: ServerResponse): Promise<void> {
|
|
29
|
+
return writeResponse(res, 204, '', contentTypes.text);
|
|
30
|
+
}
|
|
30
31
|
}
|
|
@@ -44,7 +44,7 @@ export default class ConfigGetRoute extends HTTPRoute {
|
|
|
44
44
|
method = Methods.get;
|
|
45
45
|
path = HTTPManagementRoutes.config;
|
|
46
46
|
tags = [APITags.management];
|
|
47
|
-
|
|
47
|
+
async handler(_req: Request, res: ServerResponse): Promise<void> {
|
|
48
48
|
const config = this.config();
|
|
49
49
|
|
|
50
50
|
const response: ResponseSchema = {
|
|
@@ -71,5 +71,5 @@ export default class ConfigGetRoute extends HTTPRoute {
|
|
|
71
71
|
};
|
|
72
72
|
|
|
73
73
|
return jsonResponse(res, 200, response);
|
|
74
|
-
}
|
|
74
|
+
}
|
|
75
75
|
}
|
|
@@ -26,7 +26,7 @@ export default class MetricsTotalGetRoute extends HTTPRoute {
|
|
|
26
26
|
method = Methods.get;
|
|
27
27
|
path = HTTPManagementRoutes.metricsTotal;
|
|
28
28
|
tags = [APITags.management];
|
|
29
|
-
|
|
29
|
+
async handler(_req: Request, res: ServerResponse): Promise<void> {
|
|
30
30
|
const fileSystem = this.fileSystem();
|
|
31
31
|
const config = this.config();
|
|
32
32
|
const metrics = (
|
|
@@ -76,5 +76,5 @@ export default class MetricsTotalGetRoute extends HTTPRoute {
|
|
|
76
76
|
);
|
|
77
77
|
|
|
78
78
|
return writeResponse(res, 200, JSON.stringify(totals), contentTypes.json);
|
|
79
|
-
}
|
|
79
|
+
}
|
|
80
80
|
}
|
|
@@ -24,7 +24,7 @@ export default class MetricsGetRoute extends HTTPRoute {
|
|
|
24
24
|
method = Methods.get;
|
|
25
25
|
path = HTTPManagementRoutes.metrics;
|
|
26
26
|
tags = [APITags.management];
|
|
27
|
-
|
|
27
|
+
async handler(_req: Request, res: ServerResponse): Promise<void> {
|
|
28
28
|
const fileSystem = this.fileSystem();
|
|
29
29
|
const config = this.config();
|
|
30
30
|
|
|
@@ -32,5 +32,5 @@ export default class MetricsGetRoute extends HTTPRoute {
|
|
|
32
32
|
const response = `[${stats.join(',')}]`;
|
|
33
33
|
|
|
34
34
|
return writeResponse(res, 200, response, contentTypes.json);
|
|
35
|
-
}
|
|
35
|
+
}
|
|
36
36
|
}
|
|
@@ -81,7 +81,7 @@ export default class PressureGetRoute extends HTTPRoute {
|
|
|
81
81
|
method = Methods.get;
|
|
82
82
|
path = HTTPManagementRoutes.pressure;
|
|
83
83
|
tags = [APITags.management];
|
|
84
|
-
|
|
84
|
+
async handler(_req: Request, res: ServerResponse): Promise<void> {
|
|
85
85
|
const monitoring = this.monitoring();
|
|
86
86
|
const config = this.config();
|
|
87
87
|
const limiter = this.limiter();
|
|
@@ -135,5 +135,5 @@ export default class PressureGetRoute extends HTTPRoute {
|
|
|
135
135
|
};
|
|
136
136
|
|
|
137
137
|
return jsonResponse(res, 200, response);
|
|
138
|
-
}
|
|
138
|
+
}
|
|
139
139
|
}
|
|
@@ -24,10 +24,10 @@ export default class SessionsGetRoute extends HTTPRoute {
|
|
|
24
24
|
method = Methods.get;
|
|
25
25
|
path = HTTPManagementRoutes.sessions;
|
|
26
26
|
tags = [APITags.management];
|
|
27
|
-
|
|
27
|
+
async handler(_req: Request, res: ServerResponse): Promise<void> {
|
|
28
28
|
const browserManager = this.browserManager();
|
|
29
29
|
const response: ResponseSchema = await browserManager.getAllSessions();
|
|
30
30
|
|
|
31
31
|
return jsonResponse(res, 200, response);
|
|
32
|
-
}
|
|
32
|
+
}
|
|
33
33
|
}
|
|
@@ -60,11 +60,11 @@ export default class StaticGetRoute extends HTTPRoute {
|
|
|
60
60
|
method = Methods.get;
|
|
61
61
|
path = HTTPManagementRoutes.static;
|
|
62
62
|
tags = [APITags.management];
|
|
63
|
-
|
|
63
|
+
async handler(
|
|
64
64
|
req: Request,
|
|
65
65
|
res: ServerResponse,
|
|
66
66
|
logger: Logger,
|
|
67
|
-
): Promise<unknown>
|
|
67
|
+
): Promise<unknown> {
|
|
68
68
|
const { pathname } = req.parsed;
|
|
69
69
|
const fileCache = pathMap.get(pathname);
|
|
70
70
|
|
|
@@ -117,5 +117,5 @@ export default class StaticGetRoute extends HTTPRoute {
|
|
|
117
117
|
});
|
|
118
118
|
|
|
119
119
|
return streamFile(logger, res, foundFilePath, contentType);
|
|
120
|
-
}
|
|
120
|
+
}
|
|
121
121
|
}
|
|
@@ -24,13 +24,13 @@ export default class WebKitPlaywrightWebSocketRoute extends BrowserWebsocketRout
|
|
|
24
24
|
description = `Connect to Webkit with any playwright-compliant library.`;
|
|
25
25
|
path = [WebsocketRoutes.playwrightWebkit, WebsocketRoutes.webkitPlaywright];
|
|
26
26
|
tags = [APITags.browserWS];
|
|
27
|
-
|
|
27
|
+
async handler(
|
|
28
28
|
req: Request,
|
|
29
29
|
socket: Duplex,
|
|
30
30
|
head: Buffer,
|
|
31
31
|
_logger: Logger,
|
|
32
32
|
browser: WebkitPlaywright,
|
|
33
|
-
): Promise<void>
|
|
33
|
+
): Promise<void> {
|
|
34
34
|
const isPlaywright = req.headers['user-agent']
|
|
35
35
|
?.toLowerCase()
|
|
36
36
|
.includes('playwright');
|
|
@@ -42,5 +42,5 @@ export default class WebKitPlaywrightWebSocketRoute extends BrowserWebsocketRout
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
return browser.proxyWebSocket(req, socket, head);
|
|
45
|
-
}
|
|
45
|
+
}
|
|
46
46
|
}
|
package/src/server.ts
CHANGED
|
@@ -61,30 +61,28 @@ export class HTTPServer extends EventEmitter {
|
|
|
61
61
|
);
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
protected onHTTPUnauthorized
|
|
64
|
+
protected onHTTPUnauthorized(_req: Request, res: Response) {
|
|
65
65
|
this.logger.error(
|
|
66
66
|
`HTTP request is not properly authorized, responding with 401`,
|
|
67
67
|
);
|
|
68
68
|
this.metrics.addUnauthorized();
|
|
69
69
|
return writeResponse(res, 401, 'Bad or missing authentication.');
|
|
70
|
-
}
|
|
70
|
+
}
|
|
71
71
|
|
|
72
|
-
protected onWebsocketUnauthorized
|
|
73
|
-
_req: Request,
|
|
74
|
-
socket: stream.Duplex,
|
|
75
|
-
) => {
|
|
72
|
+
protected onWebsocketUnauthorized(_req: Request, socket: stream.Duplex) {
|
|
76
73
|
this.logger.error(
|
|
77
74
|
`Websocket request is not properly authorized, responding with 401`,
|
|
78
75
|
);
|
|
79
76
|
this.metrics.addUnauthorized();
|
|
80
77
|
return writeResponse(socket, 401, 'Bad or missing authentication.');
|
|
81
|
-
}
|
|
78
|
+
}
|
|
82
79
|
|
|
83
80
|
public async start(): Promise<void> {
|
|
84
81
|
this.logger.info(`HTTP Server is starting`);
|
|
85
82
|
|
|
86
|
-
this.server.on('request', this.handleRequest);
|
|
87
|
-
this.server.on('upgrade', this.handleWebSocket);
|
|
83
|
+
this.server.on('request', this.handleRequest.bind(this));
|
|
84
|
+
this.server.on('upgrade', this.handleWebSocket.bind(this));
|
|
85
|
+
|
|
88
86
|
const listenMessage = [
|
|
89
87
|
`HTTP Server is listening on ${this.config.getServerAddress()}`,
|
|
90
88
|
`Use ${this.config.getExternalAddress()} for API and connect calls`,
|
|
@@ -105,10 +103,10 @@ export class HTTPServer extends EventEmitter {
|
|
|
105
103
|
});
|
|
106
104
|
}
|
|
107
105
|
|
|
108
|
-
protected
|
|
106
|
+
protected async handleRequest(
|
|
109
107
|
request: http.IncomingMessage,
|
|
110
108
|
res: http.ServerResponse,
|
|
111
|
-
)
|
|
109
|
+
) {
|
|
112
110
|
this.logger.trace(
|
|
113
111
|
`Handling inbound HTTP request on "${request.method}: ${request.url}"`,
|
|
114
112
|
);
|
|
@@ -299,13 +297,13 @@ export class HTTPServer extends EventEmitter {
|
|
|
299
297
|
|
|
300
298
|
return writeResponse(res, 500, e.toString());
|
|
301
299
|
});
|
|
302
|
-
}
|
|
300
|
+
}
|
|
303
301
|
|
|
304
|
-
protected
|
|
302
|
+
protected async handleWebSocket(
|
|
305
303
|
request: http.IncomingMessage,
|
|
306
304
|
socket: stream.Duplex,
|
|
307
305
|
head: Buffer,
|
|
308
|
-
)
|
|
306
|
+
) {
|
|
309
307
|
this.logger.trace(`Handling inbound WebSocket request on "${request.url}"`);
|
|
310
308
|
|
|
311
309
|
const req = request as Request;
|
|
@@ -414,7 +412,7 @@ export class HTTPServer extends EventEmitter {
|
|
|
414
412
|
`No matching WebSocket route handler for "${req.parsed.href}"`,
|
|
415
413
|
);
|
|
416
414
|
return writeResponse(socket, 404, 'Not Found');
|
|
417
|
-
}
|
|
415
|
+
}
|
|
418
416
|
|
|
419
417
|
public async shutdown(): Promise<void> {
|
|
420
418
|
this.logger.info(`HTTP Server is shutting down`);
|
|
@@ -429,5 +427,5 @@ export class HTTPServer extends EventEmitter {
|
|
|
429
427
|
/**
|
|
430
428
|
* Left blank for downstream SDK modules to optionally implement.
|
|
431
429
|
*/
|
|
432
|
-
public stop
|
|
430
|
+
public stop() {}
|
|
433
431
|
}
|
package/src/shared/browser.ws.ts
CHANGED
|
@@ -28,11 +28,13 @@ export default class ChromiumBrowserWebSocketRoute extends BrowserWebsocketRoute
|
|
|
28
28
|
);
|
|
29
29
|
path = WebsocketRoutes.browser;
|
|
30
30
|
tags = [APITags.browserWS];
|
|
31
|
-
|
|
31
|
+
async handler(
|
|
32
32
|
req: Request,
|
|
33
33
|
socket: Duplex,
|
|
34
34
|
head: Buffer,
|
|
35
35
|
_logger: Logger,
|
|
36
36
|
browser: ChromiumCDP,
|
|
37
|
-
): Promise<void>
|
|
37
|
+
): Promise<void> {
|
|
38
|
+
return browser.proxyWebSocket(req, socket, head);
|
|
39
|
+
}
|
|
38
40
|
}
|
|
@@ -27,13 +27,13 @@ export default class ChromiumPlaywrightWebSocketRoute extends BrowserWebsocketRo
|
|
|
27
27
|
WebsocketRoutes.chromiumPlaywright,
|
|
28
28
|
];
|
|
29
29
|
tags = [APITags.browserWS];
|
|
30
|
-
|
|
30
|
+
async handler(
|
|
31
31
|
req: Request,
|
|
32
32
|
socket: Duplex,
|
|
33
33
|
head: Buffer,
|
|
34
34
|
_logger: Logger,
|
|
35
35
|
browser: ChromiumPlaywright,
|
|
36
|
-
): Promise<void>
|
|
36
|
+
): Promise<void> {
|
|
37
37
|
const isPlaywright = req.headers['user-agent']
|
|
38
38
|
?.toLowerCase()
|
|
39
39
|
.includes('playwright');
|
|
@@ -45,5 +45,5 @@ export default class ChromiumPlaywrightWebSocketRoute extends BrowserWebsocketRo
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
return browser.proxyWebSocket(req, socket, head);
|
|
48
|
-
}
|
|
48
|
+
}
|
|
49
49
|
}
|
|
@@ -23,11 +23,13 @@ export default class ChromiumCDPWebSocketRoute extends BrowserWebsocketRoute {
|
|
|
23
23
|
description = `Launch and connect to Chromium with a library like puppeteer or others that work over chrome-devtools-protocol.`;
|
|
24
24
|
path = [WebsocketRoutes['/'], WebsocketRoutes.chromium];
|
|
25
25
|
tags = [APITags.browserWS];
|
|
26
|
-
|
|
26
|
+
async handler(
|
|
27
27
|
req: Request,
|
|
28
28
|
socket: Duplex,
|
|
29
29
|
head: Buffer,
|
|
30
30
|
_logger: Logger,
|
|
31
31
|
browser: ChromiumCDP,
|
|
32
|
-
): Promise<void>
|
|
32
|
+
): Promise<void> {
|
|
33
|
+
return browser.proxyWebSocket(req, socket, head);
|
|
34
|
+
}
|
|
33
35
|
}
|
|
@@ -75,12 +75,12 @@ export default class ChromiumContentPostRoute extends BrowserHTTPRoute {
|
|
|
75
75
|
method = Methods.post;
|
|
76
76
|
path = [HTTPRoutes.content, HTTPRoutes.chromiumContent];
|
|
77
77
|
tags = [APITags.browserAPI];
|
|
78
|
-
|
|
78
|
+
async handler(
|
|
79
79
|
req: Request,
|
|
80
80
|
res: ServerResponse,
|
|
81
81
|
logger: Logger,
|
|
82
82
|
browser: BrowserInstance,
|
|
83
|
-
): Promise<void>
|
|
83
|
+
): Promise<void> {
|
|
84
84
|
logger.info('Content API invoked with body:', req.body);
|
|
85
85
|
const contentType =
|
|
86
86
|
!req.headers.accept || req.headers.accept?.includes('*')
|
|
@@ -238,5 +238,5 @@ export default class ChromiumContentPostRoute extends BrowserHTTPRoute {
|
|
|
238
238
|
logger.info('Content API request completed');
|
|
239
239
|
|
|
240
240
|
return writeResponse(res, 200, markup, contentTypes.html);
|
|
241
|
-
}
|
|
241
|
+
}
|
|
242
242
|
}
|
|
@@ -59,13 +59,13 @@ export default class ChromiumDownloadPostRoute extends BrowserHTTPRoute {
|
|
|
59
59
|
method = Methods.post;
|
|
60
60
|
path = [HTTPRoutes.download, HTTPRoutes.chromiumDownload];
|
|
61
61
|
tags = [APITags.browserAPI];
|
|
62
|
-
|
|
62
|
+
async handler(
|
|
63
63
|
req: Request,
|
|
64
64
|
res: ServerResponse,
|
|
65
65
|
logger: Logger,
|
|
66
66
|
browser: BrowserInstance,
|
|
67
|
-
): Promise<void>
|
|
68
|
-
new Promise(async (resolve, reject) => {
|
|
67
|
+
): Promise<void> {
|
|
68
|
+
return new Promise(async (resolve, reject) => {
|
|
69
69
|
const config = this.config();
|
|
70
70
|
const downloadPath = path.join(
|
|
71
71
|
await config.getDownloadsDir(),
|
|
@@ -153,4 +153,5 @@ export default class ChromiumDownloadPostRoute extends BrowserHTTPRoute {
|
|
|
153
153
|
})
|
|
154
154
|
.pipe(res);
|
|
155
155
|
});
|
|
156
|
+
}
|
|
156
157
|
}
|
|
@@ -55,12 +55,12 @@ export default class ChromiumFunctionPostRoute extends BrowserHTTPRoute {
|
|
|
55
55
|
method = Methods.post;
|
|
56
56
|
path = [HTTPRoutes.function, HTTPRoutes.chromiumFunction];
|
|
57
57
|
tags = [APITags.browserAPI];
|
|
58
|
-
|
|
58
|
+
async handler(
|
|
59
59
|
req: Request,
|
|
60
60
|
res: ServerResponse,
|
|
61
61
|
logger: Logger,
|
|
62
62
|
browser: BrowserInstance,
|
|
63
|
-
): Promise<void>
|
|
63
|
+
): Promise<void> {
|
|
64
64
|
const config = this.config();
|
|
65
65
|
const handler = functionHandler(config, logger);
|
|
66
66
|
const { contentType, payload, page } = await handler(req, browser);
|
|
@@ -88,5 +88,5 @@ export default class ChromiumFunctionPostRoute extends BrowserHTTPRoute {
|
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
return;
|
|
91
|
-
}
|
|
91
|
+
}
|
|
92
92
|
}
|
|
@@ -30,8 +30,8 @@ export default class ChromiumJSONListGetRoute extends HTTPRoute {
|
|
|
30
30
|
path = HTTPRoutes.jsonList;
|
|
31
31
|
tags = [APITags.browserAPI];
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
async handler(_req: Request, res: Response): Promise<void> {
|
|
34
34
|
const browserManage = this.browserManager();
|
|
35
35
|
return jsonResponse(res, 200, await browserManage.getJSONList());
|
|
36
|
-
}
|
|
36
|
+
}
|
|
37
37
|
}
|
|
@@ -44,7 +44,7 @@ export default class ChromiumJSONNewPutRoute extends HTTPRoute {
|
|
|
44
44
|
path = HTTPRoutes.jsonNew;
|
|
45
45
|
tags = [APITags.browserAPI];
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
async handler(_req: Request, res: Response): Promise<void> {
|
|
48
48
|
const config = this.config();
|
|
49
49
|
const externalAddress = config.getExternalWebSocketAddress();
|
|
50
50
|
const id = pageID();
|
|
@@ -64,5 +64,5 @@ export default class ChromiumJSONNewPutRoute extends HTTPRoute {
|
|
|
64
64
|
url: 'about:blank',
|
|
65
65
|
webSocketDebuggerUrl: href,
|
|
66
66
|
});
|
|
67
|
-
}
|
|
67
|
+
}
|
|
68
68
|
}
|