@browserless.io/browserless 2.24.3 → 2.25.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 +17 -1
- package/README.md +1 -1
- package/build/browserless.js +3 -1
- package/build/browsers/browsers.cdp.d.ts +3 -0
- package/build/browsers/browsers.cdp.js +4 -1
- package/build/browsers/browsers.playwright.d.ts +4 -0
- package/build/browsers/browsers.playwright.js +5 -1
- package/build/browsers/index.js +3 -2
- package/build/http.d.ts +9 -0
- package/build/http.js +9 -0
- package/build/routes/chrome/http/content.post.body.json +8 -8
- 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/chrome/tests/kill-sessions.spec.js +1 -1
- 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/chromium/tests/kill-sessions.spec.js +1 -1
- package/build/routes/edge/http/content.post.body.json +579 -0
- package/build/routes/edge/http/content.post.d.ts +8 -0
- package/build/routes/edge/http/content.post.js +7 -0
- package/build/routes/edge/http/content.post.query.json +183 -0
- package/build/routes/edge/http/content.post.response.json +5 -0
- package/build/routes/edge/http/download.post.body.json +32 -0
- package/build/routes/edge/http/download.post.d.ts +8 -0
- package/build/routes/edge/http/download.post.js +7 -0
- package/build/routes/edge/http/download.post.query.json +120 -0
- package/build/routes/edge/http/download.post.response.json +4 -0
- package/build/routes/edge/http/function.post.body.json +32 -0
- package/build/routes/edge/http/function.post.d.ts +8 -0
- package/build/routes/edge/http/function.post.js +7 -0
- package/build/routes/edge/http/function.post.query.json +120 -0
- package/build/routes/edge/http/function.post.response.json +4 -0
- package/build/routes/edge/http/json-list.get.d.ts +5 -0
- package/build/routes/edge/http/json-list.get.js +5 -0
- package/build/routes/edge/http/json-list.get.response.json +52 -0
- package/build/routes/edge/http/json-new.put.d.ts +5 -0
- package/build/routes/edge/http/json-new.put.js +5 -0
- package/build/routes/edge/http/json-new.put.response.json +44 -0
- package/build/routes/edge/http/json-protocol.get.d.ts +5 -0
- package/build/routes/edge/http/json-protocol.get.js +5 -0
- package/build/routes/edge/http/json-protocol.get.response.json +6 -0
- package/build/routes/edge/http/json-version.get.d.ts +5 -0
- package/build/routes/edge/http/json-version.get.js +5 -0
- package/build/routes/edge/http/json-version.get.response.json +44 -0
- package/build/routes/edge/http/pdf.post.body.json +724 -0
- package/build/routes/edge/http/pdf.post.d.ts +8 -0
- package/build/routes/edge/http/pdf.post.js +7 -0
- package/build/routes/edge/http/pdf.post.query.json +120 -0
- package/build/routes/edge/http/pdf.post.response.json +5 -0
- package/build/routes/edge/http/performance.post.body.json +26 -0
- package/build/routes/edge/http/performance.post.d.ts +8 -0
- package/build/routes/edge/http/performance.post.js +7 -0
- package/build/routes/edge/http/performance.post.query.json +120 -0
- package/build/routes/edge/http/performance.post.response.json +7 -0
- package/build/routes/edge/http/scrape.post.body.json +626 -0
- package/build/routes/edge/http/scrape.post.d.ts +8 -0
- package/build/routes/edge/http/scrape.post.js +7 -0
- package/build/routes/edge/http/scrape.post.query.json +183 -0
- package/build/routes/edge/http/scrape.post.response.json +334 -0
- package/build/routes/edge/http/screenshot.post.body.json +669 -0
- package/build/routes/edge/http/screenshot.post.d.ts +8 -0
- package/build/routes/edge/http/screenshot.post.js +7 -0
- package/build/routes/edge/http/screenshot.post.query.json +120 -0
- package/build/routes/edge/http/screenshot.post.response.json +5 -0
- package/build/routes/edge/tests/content.spec.d.ts +1 -0
- package/build/routes/edge/tests/content.spec.js +312 -0
- package/build/routes/edge/tests/download.spec.d.ts +1 -0
- package/build/routes/edge/tests/download.spec.js +67 -0
- package/build/routes/edge/tests/function.spec.d.ts +1 -0
- package/build/routes/edge/tests/function.spec.js +277 -0
- package/build/routes/edge/tests/json-version.spec.d.ts +1 -0
- package/build/routes/edge/tests/json-version.spec.js +37 -0
- package/build/routes/edge/tests/kill-sessions.spec.d.ts +1 -0
- package/build/routes/edge/tests/kill-sessions.spec.js +80 -0
- package/build/routes/edge/tests/page-websocket.spec.d.ts +1 -0
- package/build/routes/edge/tests/page-websocket.spec.js +97 -0
- package/build/routes/edge/tests/pdf.spec.d.ts +1 -0
- package/build/routes/edge/tests/pdf.spec.js +345 -0
- package/build/routes/edge/tests/performance.spec.d.ts +1 -0
- package/build/routes/edge/tests/performance.spec.js +124 -0
- package/build/routes/edge/tests/scrape.spec.d.ts +1 -0
- package/build/routes/edge/tests/scrape.spec.js +354 -0
- package/build/routes/edge/tests/screenshot.spec.d.ts +1 -0
- package/build/routes/edge/tests/screenshot.spec.js +339 -0
- package/build/routes/edge/tests/websocket.spec.d.ts +1 -0
- package/build/routes/edge/tests/websocket.spec.js +384 -0
- package/build/routes/edge/ws/browser.d.ts +7 -0
- package/build/routes/edge/ws/browser.js +6 -0
- package/build/routes/edge/ws/browser.query.json +120 -0
- package/build/routes/edge/ws/cdp.d.ts +8 -0
- package/build/routes/edge/ws/cdp.js +7 -0
- package/build/routes/edge/ws/cdp.query.json +120 -0
- package/build/routes/edge/ws/page.d.ts +8 -0
- package/build/routes/edge/ws/page.js +7 -0
- package/build/routes/edge/ws/page.query.json +120 -0
- package/build/routes/edge/ws/playwright.d.ts +8 -0
- package/build/routes/edge/ws/playwright.js +7 -0
- package/build/routes/edge/ws/playwright.query.json +100 -0
- package/build/routes/firefox/tests/kill-sessions.spec.js +1 -1
- package/build/routes/webkit/tests/kill-sessions.spec.js +1 -1
- package/build/sdk-utils.js +1 -1
- package/build/shared/scrape.http.js +2 -2
- package/build/types.d.ts +32 -0
- package/build/types.js +18 -0
- package/build/utils.d.ts +1 -0
- package/build/utils.js +16 -2
- package/docker/chrome/Dockerfile +14 -14
- package/docker/chromium/Dockerfile +14 -14
- package/docker/edge/.dockerignore +16 -0
- package/docker/edge/Dockerfile +43 -0
- package/docker/firefox/Dockerfile +14 -14
- package/docker/multi/Dockerfile +18 -18
- package/docker/sdk/Dockerfile +10 -0
- package/package.json +18 -18
- package/src/browserless.ts +4 -0
- package/src/browsers/browsers.cdp.ts +5 -0
- package/src/browsers/browsers.playwright.ts +6 -0
- package/src/browsers/index.ts +4 -1
- package/src/http.ts +9 -0
- package/src/routes/chrome/tests/kill-sessions.spec.ts +1 -1
- package/src/routes/chromium/tests/kill-sessions.spec.ts +1 -1
- package/src/routes/edge/http/content.post.ts +20 -0
- package/src/routes/edge/http/download.post.ts +20 -0
- package/src/routes/edge/http/function.post.ts +20 -0
- package/src/routes/edge/http/json-list.get.ts +7 -0
- package/src/routes/edge/http/json-new.put.ts +7 -0
- package/src/routes/edge/http/json-protocol.get.ts +7 -0
- package/src/routes/edge/http/json-version.get.ts +7 -0
- package/src/routes/edge/http/pdf.post.ts +20 -0
- package/src/routes/edge/http/performance.post.ts +20 -0
- package/src/routes/edge/http/scrape.post.ts +20 -0
- package/src/routes/edge/http/screenshot.post.ts +20 -0
- package/src/routes/edge/tests/content.spec.ts +376 -0
- package/src/routes/edge/tests/download.spec.ts +77 -0
- package/src/routes/edge/tests/function.spec.ts +317 -0
- package/src/routes/edge/tests/json-version.spec.ts +52 -0
- package/src/routes/edge/tests/kill-sessions.spec.ts +99 -0
- package/src/routes/edge/tests/page-websocket.spec.ts +129 -0
- package/src/routes/edge/tests/pdf.spec.ts +389 -0
- package/src/routes/edge/tests/performance.spec.ts +155 -0
- package/src/routes/edge/tests/scrape.spec.ts +417 -0
- package/src/routes/edge/tests/screenshot.spec.ts +387 -0
- package/src/routes/edge/tests/websocket.spec.ts +510 -0
- package/src/routes/edge/ws/browser.ts +10 -0
- package/src/routes/edge/ws/cdp.ts +17 -0
- package/src/routes/edge/ws/page.ts +10 -0
- package/src/routes/edge/ws/playwright.ts +17 -0
- package/src/routes/firefox/tests/kill-sessions.spec.ts +1 -1
- package/src/routes/webkit/tests/kill-sessions.spec.ts +1 -1
- package/src/sdk-utils.ts +1 -1
- package/src/shared/scrape.http.ts +2 -2
- package/src/types.ts +19 -0
- package/src/utils.ts +38 -16
- package/static/docs/swagger.json +2097 -10
- package/static/docs/swagger.min.json +2096 -9
- package/static/function/client.js +76 -68
- package/static/function/index.html +76 -68
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
import { Browserless, Config, Metrics } from '@browserless.io/browserless';
|
|
2
|
+
import { expect } from 'chai';
|
|
3
|
+
describe('/edge/function API', function () {
|
|
4
|
+
let browserless;
|
|
5
|
+
const start = ({ config = new Config(), metrics = new Metrics(), } = {}) => {
|
|
6
|
+
browserless = new Browserless({ config, metrics });
|
|
7
|
+
return browserless.start();
|
|
8
|
+
};
|
|
9
|
+
afterEach(async () => {
|
|
10
|
+
await browserless.stop();
|
|
11
|
+
});
|
|
12
|
+
it('runs functions', async () => {
|
|
13
|
+
const config = new Config();
|
|
14
|
+
config.setToken('browserless');
|
|
15
|
+
const metrics = new Metrics();
|
|
16
|
+
await start({ config, metrics });
|
|
17
|
+
const body = {
|
|
18
|
+
code: `export default async function ({ page }) {
|
|
19
|
+
return Promise.resolve({
|
|
20
|
+
data: "ok",
|
|
21
|
+
type: "application/text",
|
|
22
|
+
});
|
|
23
|
+
}`,
|
|
24
|
+
context: {},
|
|
25
|
+
};
|
|
26
|
+
await fetch('http://localhost:3000/edge/function?token=browserless', {
|
|
27
|
+
body: JSON.stringify(body),
|
|
28
|
+
headers: {
|
|
29
|
+
'content-type': 'application/json',
|
|
30
|
+
},
|
|
31
|
+
method: 'POST',
|
|
32
|
+
}).then(async (res) => {
|
|
33
|
+
const json = await res.json();
|
|
34
|
+
expect(json).to.have.property('data');
|
|
35
|
+
expect(json.data).to.equal('ok');
|
|
36
|
+
expect(res.status).to.equal(200);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
it('runs functions with "context"', async () => {
|
|
40
|
+
const config = new Config();
|
|
41
|
+
config.setToken('browserless');
|
|
42
|
+
const metrics = new Metrics();
|
|
43
|
+
await start({ config, metrics });
|
|
44
|
+
const body = {
|
|
45
|
+
code: `export default async function ({ page, context }) {
|
|
46
|
+
if (!!context.ok) {
|
|
47
|
+
return Promise.resolve({
|
|
48
|
+
data: "ok",
|
|
49
|
+
type: "application/text",
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
return Promise.reject(new Error('Bad context!'));
|
|
53
|
+
}`,
|
|
54
|
+
context: {
|
|
55
|
+
ok: true,
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
await fetch('http://localhost:3000/edge/function?token=browserless', {
|
|
59
|
+
body: JSON.stringify(body),
|
|
60
|
+
headers: {
|
|
61
|
+
'content-type': 'application/json',
|
|
62
|
+
},
|
|
63
|
+
method: 'POST',
|
|
64
|
+
}).then(async (res) => {
|
|
65
|
+
const json = await res.json();
|
|
66
|
+
expect(json).to.have.property('data');
|
|
67
|
+
expect(json.data).to.equal('ok');
|
|
68
|
+
expect(res.status).to.equal(200);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
it('runs "application/javascript" functions', async () => {
|
|
72
|
+
const config = new Config();
|
|
73
|
+
config.setToken('browserless');
|
|
74
|
+
const metrics = new Metrics();
|
|
75
|
+
await start({ config, metrics });
|
|
76
|
+
const body = `export default async function ({ page }) {
|
|
77
|
+
return Promise.resolve({
|
|
78
|
+
data: "ok",
|
|
79
|
+
type: "application/text",
|
|
80
|
+
});
|
|
81
|
+
}`;
|
|
82
|
+
await fetch('http://localhost:3000/edge/function?token=browserless', {
|
|
83
|
+
body,
|
|
84
|
+
headers: { 'Content-Type': 'application/javascript' },
|
|
85
|
+
method: 'POST',
|
|
86
|
+
}).then(async (res) => {
|
|
87
|
+
const json = await res.json();
|
|
88
|
+
expect(json).to.have.property('data');
|
|
89
|
+
expect(json.data).to.equal('ok');
|
|
90
|
+
expect(json.type).to.equal('application/text');
|
|
91
|
+
expect(res.status).to.equal(200);
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
it('runs functions that import libraries', async () => {
|
|
95
|
+
const config = new Config();
|
|
96
|
+
config.setToken('browserless');
|
|
97
|
+
const metrics = new Metrics();
|
|
98
|
+
await start({ config, metrics });
|
|
99
|
+
const body = {
|
|
100
|
+
code: `
|
|
101
|
+
import 'https://code.jquery.com/jquery-3.6.0.min.js';
|
|
102
|
+
export default async function ({ page }) {
|
|
103
|
+
return Promise.resolve({
|
|
104
|
+
data: typeof window.jQuery,
|
|
105
|
+
});
|
|
106
|
+
}`,
|
|
107
|
+
context: {},
|
|
108
|
+
};
|
|
109
|
+
await fetch('http://localhost:3000/edge/function?token=browserless', {
|
|
110
|
+
body: JSON.stringify(body),
|
|
111
|
+
headers: {
|
|
112
|
+
'content-type': 'application/json',
|
|
113
|
+
},
|
|
114
|
+
method: 'POST',
|
|
115
|
+
}).then(async (res) => {
|
|
116
|
+
const json = await res.json();
|
|
117
|
+
expect(json).to.have.property('data');
|
|
118
|
+
expect(json.data).to.equal('function');
|
|
119
|
+
expect(res.status).to.equal(200);
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
it('runs functions with custom return types', async () => {
|
|
123
|
+
const config = new Config();
|
|
124
|
+
config.setToken('browserless');
|
|
125
|
+
const metrics = new Metrics();
|
|
126
|
+
await start({ config, metrics });
|
|
127
|
+
const body = {
|
|
128
|
+
code: `
|
|
129
|
+
export default async function ({ page }) {
|
|
130
|
+
return Promise.resolve({
|
|
131
|
+
data: {
|
|
132
|
+
status: 'ok',
|
|
133
|
+
},
|
|
134
|
+
});
|
|
135
|
+
}`,
|
|
136
|
+
context: {},
|
|
137
|
+
};
|
|
138
|
+
await fetch('http://localhost:3000/edge/function?token=browserless', {
|
|
139
|
+
body: JSON.stringify(body),
|
|
140
|
+
headers: {
|
|
141
|
+
'content-type': 'application/json',
|
|
142
|
+
},
|
|
143
|
+
method: 'POST',
|
|
144
|
+
}).then(async (res) => {
|
|
145
|
+
const json = await res.json();
|
|
146
|
+
expect(res.headers.get('content-type')).to.equal(`application/json; charset=UTF-8`);
|
|
147
|
+
expect(json).to.have.property('data');
|
|
148
|
+
expect(res.status).to.equal(200);
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
it('times out requests', async () => {
|
|
152
|
+
const config = new Config();
|
|
153
|
+
config.setToken('browserless');
|
|
154
|
+
const metrics = new Metrics();
|
|
155
|
+
await start({ config, metrics });
|
|
156
|
+
const body = {
|
|
157
|
+
code: `export default async function ({ page }) {
|
|
158
|
+
return Promise.resolve({
|
|
159
|
+
data: "ok",
|
|
160
|
+
type: "application/text",
|
|
161
|
+
});
|
|
162
|
+
}`,
|
|
163
|
+
context: {},
|
|
164
|
+
};
|
|
165
|
+
await fetch('http://localhost:3000/edge/function?token=browserless&timeout=10', {
|
|
166
|
+
body: JSON.stringify(body),
|
|
167
|
+
headers: {
|
|
168
|
+
'content-type': 'application/json',
|
|
169
|
+
},
|
|
170
|
+
method: 'POST',
|
|
171
|
+
}).then((res) => {
|
|
172
|
+
expect(res.status).to.equal(408);
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
it('rejects requests with bad content-types', async () => {
|
|
176
|
+
const config = new Config();
|
|
177
|
+
config.setConcurrent(0);
|
|
178
|
+
config.setQueued(0);
|
|
179
|
+
config.setToken('browserless');
|
|
180
|
+
const metrics = new Metrics();
|
|
181
|
+
await start({ config, metrics });
|
|
182
|
+
const body = {
|
|
183
|
+
code: `export default async function ({ page }) {
|
|
184
|
+
return Promise.resolve({
|
|
185
|
+
data: "ok",
|
|
186
|
+
type: "application/text",
|
|
187
|
+
});
|
|
188
|
+
}`,
|
|
189
|
+
context: {},
|
|
190
|
+
};
|
|
191
|
+
await fetch('http://localhost:3000/edge/function?token=browserless', {
|
|
192
|
+
body: JSON.stringify(body),
|
|
193
|
+
headers: {
|
|
194
|
+
'content-type': 'joelson',
|
|
195
|
+
},
|
|
196
|
+
method: 'POST',
|
|
197
|
+
}).then(async (res) => {
|
|
198
|
+
return expect(res.status).to.equal(404);
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
it('rejects requests with 429', async () => {
|
|
202
|
+
const config = new Config();
|
|
203
|
+
config.setConcurrent(0);
|
|
204
|
+
config.setQueued(0);
|
|
205
|
+
config.setToken('browserless');
|
|
206
|
+
const metrics = new Metrics();
|
|
207
|
+
await start({ config, metrics });
|
|
208
|
+
const body = {
|
|
209
|
+
code: `export default async function ({ page }) {
|
|
210
|
+
return Promise.resolve({
|
|
211
|
+
data: "ok",
|
|
212
|
+
type: "application/text",
|
|
213
|
+
});
|
|
214
|
+
}`,
|
|
215
|
+
context: {},
|
|
216
|
+
};
|
|
217
|
+
await fetch('http://localhost:3000/edge/function?token=browserless', {
|
|
218
|
+
body: JSON.stringify(body),
|
|
219
|
+
headers: {
|
|
220
|
+
'content-type': 'application/json',
|
|
221
|
+
},
|
|
222
|
+
method: 'POST',
|
|
223
|
+
}).then(async (res) => {
|
|
224
|
+
return expect(res.status).to.equal(429);
|
|
225
|
+
});
|
|
226
|
+
});
|
|
227
|
+
it('rejects requests that are unauthorized', async () => {
|
|
228
|
+
const config = new Config();
|
|
229
|
+
config.setToken('browserless');
|
|
230
|
+
const metrics = new Metrics();
|
|
231
|
+
await start({ config, metrics });
|
|
232
|
+
const body = {
|
|
233
|
+
code: `export default async function ({ page }) {
|
|
234
|
+
return Promise.resolve({
|
|
235
|
+
data: "ok",
|
|
236
|
+
type: "application/text",
|
|
237
|
+
});
|
|
238
|
+
}`,
|
|
239
|
+
context: {},
|
|
240
|
+
};
|
|
241
|
+
await fetch('http://localhost:3000/edge/function?token=bless', {
|
|
242
|
+
body: JSON.stringify(body),
|
|
243
|
+
headers: {
|
|
244
|
+
'content-type': 'application/json',
|
|
245
|
+
},
|
|
246
|
+
method: 'POST',
|
|
247
|
+
}).then(async (res) => {
|
|
248
|
+
return expect(res.status).to.equal(401);
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
it('allows requests without token when auth token is not set', async () => {
|
|
252
|
+
const config = new Config();
|
|
253
|
+
const metrics = new Metrics();
|
|
254
|
+
await start({ config, metrics });
|
|
255
|
+
const body = {
|
|
256
|
+
code: `export default async function ({ page }) {
|
|
257
|
+
return Promise.resolve({
|
|
258
|
+
data: "ok",
|
|
259
|
+
type: "application/text",
|
|
260
|
+
});
|
|
261
|
+
}`,
|
|
262
|
+
context: {},
|
|
263
|
+
};
|
|
264
|
+
await fetch('http://localhost:3000/edge/function', {
|
|
265
|
+
body: JSON.stringify(body),
|
|
266
|
+
headers: {
|
|
267
|
+
'content-type': 'application/json',
|
|
268
|
+
},
|
|
269
|
+
method: 'POST',
|
|
270
|
+
}).then(async (res) => {
|
|
271
|
+
const json = await res.json();
|
|
272
|
+
expect(json).to.have.property('data');
|
|
273
|
+
expect(json.data).to.equal('ok');
|
|
274
|
+
expect(res.status).to.equal(200);
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Browserless, Config, Metrics } from '@browserless.io/browserless';
|
|
2
|
+
import { expect } from 'chai';
|
|
3
|
+
describe('/json/version API', function () {
|
|
4
|
+
let browserless;
|
|
5
|
+
const start = ({ config = new Config(), metrics = new Metrics(), } = {}) => {
|
|
6
|
+
browserless = new Browserless({ config, metrics });
|
|
7
|
+
return browserless.start();
|
|
8
|
+
};
|
|
9
|
+
afterEach(async () => {
|
|
10
|
+
await browserless.stop();
|
|
11
|
+
});
|
|
12
|
+
it('allows requests to /json/version', async () => {
|
|
13
|
+
const config = new Config();
|
|
14
|
+
config.setToken('browserless');
|
|
15
|
+
const metrics = new Metrics();
|
|
16
|
+
await start({ config, metrics });
|
|
17
|
+
const res = await fetch('http://localhost:3000/json/version?token=browserless');
|
|
18
|
+
const resJSON = await res.json();
|
|
19
|
+
[
|
|
20
|
+
'Browser',
|
|
21
|
+
'Protocol-Version',
|
|
22
|
+
'User-Agent',
|
|
23
|
+
'V8-Version',
|
|
24
|
+
'WebKit-Version',
|
|
25
|
+
'webSocketDebuggerUrl',
|
|
26
|
+
'Debugger-Version',
|
|
27
|
+
].forEach((k) => expect(resJSON).to.haveOwnProperty(k));
|
|
28
|
+
});
|
|
29
|
+
it('rejects unauthorized requests to /json/version', async () => {
|
|
30
|
+
const config = new Config();
|
|
31
|
+
config.setToken('browserless');
|
|
32
|
+
const metrics = new Metrics();
|
|
33
|
+
await start({ config, metrics });
|
|
34
|
+
const res = await fetch('http://localhost:3000/json/version?token=imabadboi');
|
|
35
|
+
expect(res.status).to.equal(401);
|
|
36
|
+
});
|
|
37
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { Browserless, Config, Metrics } from '@browserless.io/browserless';
|
|
2
|
+
import { expect } from 'chai';
|
|
3
|
+
import puppeteer from 'puppeteer-core';
|
|
4
|
+
describe('/kill API', function () {
|
|
5
|
+
let browserless;
|
|
6
|
+
const start = ({ config = new Config(), metrics = new Metrics(), } = {}) => {
|
|
7
|
+
config.setToken('6R0W53R135510');
|
|
8
|
+
browserless = new Browserless({ config, metrics });
|
|
9
|
+
return browserless.start();
|
|
10
|
+
};
|
|
11
|
+
afterEach(async () => {
|
|
12
|
+
await browserless.stop();
|
|
13
|
+
});
|
|
14
|
+
it('Kill all sessions', async () => {
|
|
15
|
+
await start();
|
|
16
|
+
const browser1 = await puppeteer.connect({
|
|
17
|
+
browserWSEndpoint: `ws://localhost:3000/edge?token=6R0W53R135510`,
|
|
18
|
+
});
|
|
19
|
+
const browser2 = await puppeteer.connect({
|
|
20
|
+
browserWSEndpoint: `ws://localhost:3000/edge?token=6R0W53R135510`,
|
|
21
|
+
});
|
|
22
|
+
await fetch('http://localhost:3000/kill/all?token=6R0W53R135510').then(async (res) => {
|
|
23
|
+
expect(res.status).to.equal(204);
|
|
24
|
+
});
|
|
25
|
+
let errorThrown1;
|
|
26
|
+
try {
|
|
27
|
+
await browser1.newPage();
|
|
28
|
+
}
|
|
29
|
+
catch (e) {
|
|
30
|
+
errorThrown1 = e;
|
|
31
|
+
}
|
|
32
|
+
let errorThrown2;
|
|
33
|
+
try {
|
|
34
|
+
await browser2.newPage();
|
|
35
|
+
}
|
|
36
|
+
catch (e) {
|
|
37
|
+
errorThrown2 = e;
|
|
38
|
+
}
|
|
39
|
+
expect(errorThrown1.message).contains('closed');
|
|
40
|
+
expect(errorThrown2.message).contains('closed');
|
|
41
|
+
});
|
|
42
|
+
it('Kill session by browserId', async () => {
|
|
43
|
+
await start();
|
|
44
|
+
const browser = await puppeteer.connect({
|
|
45
|
+
browserWSEndpoint: `ws://localhost:3000/edge?token=6R0W53R135510`,
|
|
46
|
+
});
|
|
47
|
+
await fetch('http://localhost:3000/sessions?token=6R0W53R135510').then(async (res) => {
|
|
48
|
+
const sessions = await res.json();
|
|
49
|
+
const browserId = sessions[0].browserId;
|
|
50
|
+
await fetch(`http://localhost:3000/kill/${browserId}?token=6R0W53R135510`).then(async (res) => {
|
|
51
|
+
expect(res.status).to.equal(204);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
let errorThrown;
|
|
55
|
+
try {
|
|
56
|
+
await browser.newPage();
|
|
57
|
+
}
|
|
58
|
+
catch (e) {
|
|
59
|
+
errorThrown = e;
|
|
60
|
+
}
|
|
61
|
+
expect(errorThrown.message).contains('closed');
|
|
62
|
+
});
|
|
63
|
+
it('Kill session by trackingId', async () => {
|
|
64
|
+
await start();
|
|
65
|
+
const browser = await puppeteer.connect({
|
|
66
|
+
browserWSEndpoint: `ws://localhost:3000/edge?token=6R0W53R135510&trackingId=session-1`,
|
|
67
|
+
});
|
|
68
|
+
await fetch('http://localhost:3000/kill/session-1?token=6R0W53R135510').then(async (res) => {
|
|
69
|
+
expect(res.status).to.equal(204);
|
|
70
|
+
});
|
|
71
|
+
let errorThrown;
|
|
72
|
+
try {
|
|
73
|
+
await browser.newPage();
|
|
74
|
+
}
|
|
75
|
+
catch (e) {
|
|
76
|
+
errorThrown = e;
|
|
77
|
+
}
|
|
78
|
+
expect(errorThrown.message).contains('closed');
|
|
79
|
+
});
|
|
80
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { Browserless, Config, Metrics } from '@browserless.io/browserless';
|
|
2
|
+
import puppeteer, { Connection } from 'puppeteer-core';
|
|
3
|
+
import { NodeWebSocketTransport } from 'puppeteer-core/lib/esm/puppeteer/node/NodeWebSocketTransport.js';
|
|
4
|
+
import { expect } from 'chai';
|
|
5
|
+
describe('WebSocket Page API', function () {
|
|
6
|
+
// Server shutdown can take a few seconds
|
|
7
|
+
// and so can these tests :/
|
|
8
|
+
this.timeout(5000);
|
|
9
|
+
let browserless;
|
|
10
|
+
const start = ({ config = new Config(), metrics = new Metrics(), } = {}) => {
|
|
11
|
+
browserless = new Browserless({ config, metrics });
|
|
12
|
+
return browserless.start();
|
|
13
|
+
};
|
|
14
|
+
afterEach(async () => {
|
|
15
|
+
await browserless.stop();
|
|
16
|
+
});
|
|
17
|
+
it('forwards requests to running pages', async () => {
|
|
18
|
+
const config = new Config();
|
|
19
|
+
const metrics = new Metrics();
|
|
20
|
+
await start({ config, metrics });
|
|
21
|
+
const browser = await puppeteer.connect({
|
|
22
|
+
browserWSEndpoint: `ws://localhost:3000/edge`,
|
|
23
|
+
});
|
|
24
|
+
const page = await browser.newPage();
|
|
25
|
+
await page.goto('https://example.com/');
|
|
26
|
+
// @ts-ignore
|
|
27
|
+
const pageId = page.target()._targetId;
|
|
28
|
+
const webSocketDebuggerUrl = `ws://localhost:3000/devtools/page/${pageId}`;
|
|
29
|
+
// Connect to raw page target
|
|
30
|
+
const cdp = new Connection(webSocketDebuggerUrl, await NodeWebSocketTransport.create(webSocketDebuggerUrl));
|
|
31
|
+
// Send a command
|
|
32
|
+
const result = await cdp.send('Page.enable');
|
|
33
|
+
await browser.close();
|
|
34
|
+
expect(result);
|
|
35
|
+
});
|
|
36
|
+
it('creates pages when interacting with /json/new', async () => {
|
|
37
|
+
const config = new Config();
|
|
38
|
+
const metrics = new Metrics();
|
|
39
|
+
await start({ config, metrics });
|
|
40
|
+
const { webSocketDebuggerUrl } = await fetch('http://localhost:3000/json/new', {
|
|
41
|
+
method: 'PUT',
|
|
42
|
+
}).then((r) => r.json());
|
|
43
|
+
// Connect to raw page target
|
|
44
|
+
const cdp = new Connection(webSocketDebuggerUrl, await NodeWebSocketTransport.create(webSocketDebuggerUrl));
|
|
45
|
+
// Send a command
|
|
46
|
+
const result = await cdp.send('Page.enable');
|
|
47
|
+
cdp.dispose();
|
|
48
|
+
expect(result);
|
|
49
|
+
});
|
|
50
|
+
it('rejects unauthorized page requests', async () => {
|
|
51
|
+
const config = new Config();
|
|
52
|
+
config.setToken('browserless');
|
|
53
|
+
const metrics = new Metrics();
|
|
54
|
+
await start({ config, metrics });
|
|
55
|
+
const browser = await puppeteer.connect({
|
|
56
|
+
browserWSEndpoint: `ws://localhost:3000/edge?token=browserless`,
|
|
57
|
+
});
|
|
58
|
+
const page = await browser.newPage();
|
|
59
|
+
await page.goto('https://example.com/');
|
|
60
|
+
// @ts-ignore
|
|
61
|
+
const pageId = page.target()._targetId;
|
|
62
|
+
const webSocketDebuggerUrl = `ws://localhost:3000/devtools/page/${pageId}`;
|
|
63
|
+
// Connect to raw page target without authorization
|
|
64
|
+
try {
|
|
65
|
+
new Connection(webSocketDebuggerUrl, await NodeWebSocketTransport.create(webSocketDebuggerUrl));
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
//@ts-ignore
|
|
69
|
+
expect(err.message).to.include('401');
|
|
70
|
+
}
|
|
71
|
+
finally {
|
|
72
|
+
browser.close();
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
it('404s pages not found', async () => {
|
|
76
|
+
const config = new Config();
|
|
77
|
+
const metrics = new Metrics();
|
|
78
|
+
await start({ config, metrics });
|
|
79
|
+
const browser = await puppeteer.connect({
|
|
80
|
+
browserWSEndpoint: `ws://localhost:3000/edge?token=browserless`,
|
|
81
|
+
});
|
|
82
|
+
const page = await browser.newPage();
|
|
83
|
+
await page.goto('https://example.com/');
|
|
84
|
+
const webSocketDebuggerUrl = `ws://localhost:3000/devtools/page/im-a-banana`;
|
|
85
|
+
// Connect to raw page target without authorization
|
|
86
|
+
try {
|
|
87
|
+
new Connection(webSocketDebuggerUrl, await NodeWebSocketTransport.create(webSocketDebuggerUrl));
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
//@ts-ignore
|
|
91
|
+
expect(err.message).to.include('404');
|
|
92
|
+
}
|
|
93
|
+
finally {
|
|
94
|
+
browser.close();
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|