@xbrowser/cli 0.16.0 → 1.0.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/dist/{browser-R7B255ML.js → browser-53KUFEEM.js} +5 -1
- package/dist/{browser-I2HJZ7IP.js → browser-DSVV4GHS.js} +2 -2
- package/dist/{browser-GWBH6OJK.js → browser-GURRY444.js} +3 -1
- package/dist/cdp-driver-MNPR3HZH.js +2537 -0
- package/dist/cdp-driver-SSXUGXP6.js +47 -0
- package/dist/{chunk-2ONMTDLK.js → chunk-2BQZIT3S.js} +2535 -50
- package/dist/{chunk-KDYXFLAC.js → chunk-2MFXKN32.js} +2 -2
- package/dist/chunk-42RPMJ76.js +2530 -0
- package/dist/{chunk-F3ZWFCJJ.js → chunk-E4O5ZU3H.js} +2535 -50
- package/dist/{chunk-ATFTAKMN.js → chunk-IDVD44ED.js} +20 -0
- package/dist/chunk-T4J4C2NZ.js +250 -0
- package/dist/{chunk-RS6YYWTK.js → chunk-YKOHDEFV.js} +73 -38
- package/dist/cli.js +1054 -140
- package/dist/{convert-4DUWZIKH.js → convert-EGFYNICZ.js} +2 -0
- package/dist/{daemon-client-GX2UYIW4.js → daemon-client-3VM7VU7O.js} +22 -0
- package/dist/{daemon-client-3IJD6X4B.js → daemon-client-YAVQ343A.js} +7 -1
- package/dist/daemon-main.js +984 -114
- package/dist/{extract-EGRXZSSK.js → extract-L2IW3IUB.js} +2 -0
- package/dist/{filter-OLAE26HN.js → filter-HC4RA7JY.js} +2 -0
- package/dist/index.d.ts +581 -41
- package/dist/index.js +1100 -182
- package/dist/launcher-KA7J32K5.js +19 -0
- package/dist/{network-store-YAF5OIBH.js → network-store-66A2RATI.js} +1 -0
- package/dist/{session-recorder-XET3DNML.js → session-recorder-MA75PKTQ.js} +1 -1
- package/package.json +2 -3
- package/dist/daemon-client-XWSSQBEA.js +0 -58
- package/dist/network-store-2S5HATEV.js +0 -194
- package/dist/parse-action-dsl-DRSPBALP.js +0 -72
- package/dist/screenshot-MB6R7RSS.js +0 -26
- package/dist/session-recorder-ILSSV2UC.js +0 -6
|
@@ -170,6 +170,23 @@ async function forwardChain(input, session = "default", cdpEndpoint) {
|
|
|
170
170
|
return { success: false, steps: [], totalDuration: 0, stoppedReason: "Daemon error" };
|
|
171
171
|
}
|
|
172
172
|
}
|
|
173
|
+
async function forwardAgentObserve(session = "default", options) {
|
|
174
|
+
const params = { session };
|
|
175
|
+
if (options?.cdpEndpoint) params.cdpEndpoint = options.cdpEndpoint;
|
|
176
|
+
if (options?.includeHidden !== void 0) params.includeHidden = options.includeHidden;
|
|
177
|
+
if (options?.limit !== void 0) params.limit = options.limit;
|
|
178
|
+
return rpcCall("agent:observe", params, 3e4);
|
|
179
|
+
}
|
|
180
|
+
async function forwardAgentAct(session = "default", params, cdpEndpoint) {
|
|
181
|
+
const rpcParams = { ...params, session };
|
|
182
|
+
if (cdpEndpoint) rpcParams.cdpEndpoint = cdpEndpoint;
|
|
183
|
+
return rpcCall("agent:act", rpcParams, 3e4);
|
|
184
|
+
}
|
|
185
|
+
async function forwardAgentWait(session = "default", params, cdpEndpoint, timeoutMs = 3e4) {
|
|
186
|
+
const rpcParams = { ...params, session };
|
|
187
|
+
if (cdpEndpoint) rpcParams.cdpEndpoint = cdpEndpoint;
|
|
188
|
+
return rpcCall("agent:wait", rpcParams, timeoutMs + 5e3);
|
|
189
|
+
}
|
|
173
190
|
async function forwardNetworkList(sessionName, options) {
|
|
174
191
|
return rpcCall("network:list", { session: sessionName, ...options }, 3e4);
|
|
175
192
|
}
|
|
@@ -244,6 +261,9 @@ export {
|
|
|
244
261
|
forwardSessionList,
|
|
245
262
|
forwardExec,
|
|
246
263
|
forwardChain,
|
|
264
|
+
forwardAgentObserve,
|
|
265
|
+
forwardAgentAct,
|
|
266
|
+
forwardAgentWait,
|
|
247
267
|
forwardNetworkList,
|
|
248
268
|
forwardNetworkClear,
|
|
249
269
|
forwardNetworkTop,
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__require
|
|
3
|
+
} from "./chunk-3RG5ZIWI.js";
|
|
4
|
+
|
|
5
|
+
// src/cdp-driver/launcher.ts
|
|
6
|
+
import { spawn } from "child_process";
|
|
7
|
+
import { existsSync as fsExistsSync } from "fs";
|
|
8
|
+
var DEFAULT_CHROME_PATHS = {
|
|
9
|
+
darwin: [
|
|
10
|
+
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
|
|
11
|
+
"/Applications/Chromium.app/Contents/MacOS/Chromium",
|
|
12
|
+
"/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge",
|
|
13
|
+
"/Applications/Brave Browser.app/Contents/MacOS/Brave Browser"
|
|
14
|
+
],
|
|
15
|
+
linux: [
|
|
16
|
+
"/usr/bin/google-chrome",
|
|
17
|
+
"/usr/bin/google-chrome-stable",
|
|
18
|
+
"/usr/bin/chromium",
|
|
19
|
+
"/usr/bin/chromium-browser",
|
|
20
|
+
"/usr/bin/microsoft-edge"
|
|
21
|
+
],
|
|
22
|
+
win32: [
|
|
23
|
+
"C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe",
|
|
24
|
+
"C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe",
|
|
25
|
+
"C:\\Program Files\\Microsoft\\Edge\\Application\\msedge.exe"
|
|
26
|
+
]
|
|
27
|
+
};
|
|
28
|
+
var DEFAULT_ARGS = [
|
|
29
|
+
"--no-first-run",
|
|
30
|
+
"--no-default-browser-check",
|
|
31
|
+
"--no-sandbox",
|
|
32
|
+
"--disable-background-networking",
|
|
33
|
+
"--disable-background-timer-throttling",
|
|
34
|
+
"--disable-backgrounding-occluded-windows",
|
|
35
|
+
"--disable-breakpad",
|
|
36
|
+
"--disable-client-side-phishing-detection",
|
|
37
|
+
"--disable-default-apps",
|
|
38
|
+
"--disable-extensions",
|
|
39
|
+
"--disable-hang-monitor",
|
|
40
|
+
"--disable-ipc-flood-protection",
|
|
41
|
+
"--disable-popup-blocking",
|
|
42
|
+
"--disable-prompt-on-repost",
|
|
43
|
+
"--disable-renderer-backgrounding",
|
|
44
|
+
"--disable-sync",
|
|
45
|
+
"--disable-translate",
|
|
46
|
+
"--metrics-recording-only",
|
|
47
|
+
"--password-store=basic",
|
|
48
|
+
"--use-mock-keychain"
|
|
49
|
+
];
|
|
50
|
+
var ANTI_DETECT_ARGS = [
|
|
51
|
+
"--disable-blink-features=AutomationControlled",
|
|
52
|
+
"--disable-features=IsolateOrigins,site-per-process"
|
|
53
|
+
];
|
|
54
|
+
function findChrome() {
|
|
55
|
+
const platform = process.platform;
|
|
56
|
+
const paths = DEFAULT_CHROME_PATHS[platform] ?? [];
|
|
57
|
+
for (const p of paths) {
|
|
58
|
+
if (fsExistsSync(p)) return p;
|
|
59
|
+
}
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
async function launchChrome(options = {}) {
|
|
63
|
+
const {
|
|
64
|
+
executablePath,
|
|
65
|
+
headless = true,
|
|
66
|
+
args: extraArgs = [],
|
|
67
|
+
userDataDir,
|
|
68
|
+
timeout = 3e4,
|
|
69
|
+
env
|
|
70
|
+
} = options;
|
|
71
|
+
const chromePath = executablePath ?? findChrome();
|
|
72
|
+
if (!chromePath) {
|
|
73
|
+
throw new Error(
|
|
74
|
+
"Chrome/Chromium not found. Set executablePath or install Chrome to a default location."
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
const port = await findFreePort();
|
|
78
|
+
const allArgs = [
|
|
79
|
+
`--remote-debugging-port=${port}`,
|
|
80
|
+
"--remote-allow-origins=*",
|
|
81
|
+
"--no-sandbox",
|
|
82
|
+
"--no-first-run",
|
|
83
|
+
"--no-default-browser-check",
|
|
84
|
+
"--disable-background-timer-throttling",
|
|
85
|
+
"--disable-backgrounding-occluded-windows",
|
|
86
|
+
"--disable-renderer-backgrounding",
|
|
87
|
+
"--disable-features=Translate"
|
|
88
|
+
];
|
|
89
|
+
if (headless) {
|
|
90
|
+
allArgs.push("--headless", "--hide-scrollbars", "--mute-audio");
|
|
91
|
+
}
|
|
92
|
+
let tmpDir;
|
|
93
|
+
if (userDataDir) {
|
|
94
|
+
allArgs.push(`--user-data-dir=${userDataDir}`);
|
|
95
|
+
} else {
|
|
96
|
+
const { mkdirSync } = await import("fs");
|
|
97
|
+
tmpDir = `/tmp/xbrowser-chrome-${process.pid}-${Date.now()}`;
|
|
98
|
+
mkdirSync(tmpDir, { recursive: true });
|
|
99
|
+
allArgs.push(`--user-data-dir=${tmpDir}`);
|
|
100
|
+
}
|
|
101
|
+
allArgs.push(...extraArgs, "about:blank");
|
|
102
|
+
const childEnv = {
|
|
103
|
+
...process.env,
|
|
104
|
+
...env
|
|
105
|
+
};
|
|
106
|
+
const quotedPath = chromePath.includes(" ") ? `"${chromePath}"` : chromePath;
|
|
107
|
+
const quotedArgs = allArgs.map((a) => {
|
|
108
|
+
if (a.includes(" ")) return `"${a}"`;
|
|
109
|
+
return a;
|
|
110
|
+
}).join(" ");
|
|
111
|
+
const fullCmd = `${quotedPath} ${quotedArgs}`;
|
|
112
|
+
const child = process.platform === "darwin" ? spawn("/bin/sh", ["-c", fullCmd], {
|
|
113
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
114
|
+
env: childEnv
|
|
115
|
+
}) : spawn(chromePath, allArgs, {
|
|
116
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
117
|
+
env: childEnv
|
|
118
|
+
});
|
|
119
|
+
const stderrLines = [];
|
|
120
|
+
child.stderr?.on("data", (data) => {
|
|
121
|
+
const line = data.toString().trim();
|
|
122
|
+
if (line) stderrLines.push(line);
|
|
123
|
+
});
|
|
124
|
+
child.stdout?.on("data", (data) => {
|
|
125
|
+
const line = data.toString().trim();
|
|
126
|
+
if (line) stderrLines.push(`[stdout] ${line}`);
|
|
127
|
+
});
|
|
128
|
+
child.on("error", (err) => {
|
|
129
|
+
if (!child.killed) {
|
|
130
|
+
console.error(`Chrome process error: ${err.message}`);
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
try {
|
|
134
|
+
const wsEndpoint = await waitForCDPReady(port, timeout, child);
|
|
135
|
+
return { process: child, wsEndpoint, port, tmpDir };
|
|
136
|
+
} catch (err) {
|
|
137
|
+
const stderr = stderrLines.slice(-20).join("\n");
|
|
138
|
+
const exitInfo = child.exitCode !== null ? ` (exit code: ${child.exitCode})` : " (still running)";
|
|
139
|
+
throw new Error(`${err.message}${exitInfo}
|
|
140
|
+
Chrome stderr:
|
|
141
|
+
${stderr || "(empty)"}`);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
async function connectToCDP(rawEndpoint) {
|
|
145
|
+
if (rawEndpoint.startsWith("ws://") || rawEndpoint.startsWith("wss://")) {
|
|
146
|
+
return rawEndpoint;
|
|
147
|
+
}
|
|
148
|
+
return resolveEndpointFromHTTP(rawEndpoint);
|
|
149
|
+
}
|
|
150
|
+
async function findFreePort() {
|
|
151
|
+
const { createServer } = await import("net");
|
|
152
|
+
return new Promise((resolve, reject) => {
|
|
153
|
+
const srv = createServer();
|
|
154
|
+
srv.listen(0, "127.0.0.1", () => {
|
|
155
|
+
const addr = srv.address();
|
|
156
|
+
if (addr && typeof addr === "object") {
|
|
157
|
+
const port = addr.port;
|
|
158
|
+
srv.close(() => resolve(port));
|
|
159
|
+
} else {
|
|
160
|
+
srv.close();
|
|
161
|
+
reject(new Error("Failed to find free port"));
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
srv.on("error", reject);
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
async function waitForCDPReady(port, timeoutMs, child) {
|
|
168
|
+
const deadline = Date.now() + timeoutMs;
|
|
169
|
+
while (Date.now() < deadline) {
|
|
170
|
+
if (child.exitCode !== null && child.exitCode !== 0) {
|
|
171
|
+
throw new Error(`Chrome exited with code ${child.exitCode} before CDP became ready`);
|
|
172
|
+
}
|
|
173
|
+
try {
|
|
174
|
+
const wsEndpoint = await resolveEndpointFromHTTP(`http://127.0.0.1:${port}`);
|
|
175
|
+
return wsEndpoint;
|
|
176
|
+
} catch {
|
|
177
|
+
await sleep(200);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
throw new Error(`Chrome CDP not ready after ${timeoutMs}ms (port ${port})`);
|
|
181
|
+
}
|
|
182
|
+
async function resolveEndpointFromHTTP(baseURL) {
|
|
183
|
+
const url = `${baseURL}/json/version`;
|
|
184
|
+
const resp = await fetch(url, { signal: AbortSignal.timeout(3e3) });
|
|
185
|
+
if (!resp.ok) {
|
|
186
|
+
throw new Error(`CDP HTTP ${resp.status}: ${url}`);
|
|
187
|
+
}
|
|
188
|
+
const data = await resp.json();
|
|
189
|
+
if (!data.webSocketDebuggerUrl) {
|
|
190
|
+
throw new Error("No webSocketDebuggerUrl in CDP response");
|
|
191
|
+
}
|
|
192
|
+
return data.webSocketDebuggerUrl;
|
|
193
|
+
}
|
|
194
|
+
async function getCDPTargets(baseURL) {
|
|
195
|
+
const url = `${baseURL}/json/list`;
|
|
196
|
+
const resp = await fetch(url, { signal: AbortSignal.timeout(5e3) });
|
|
197
|
+
if (!resp.ok) {
|
|
198
|
+
throw new Error(`CDP list HTTP ${resp.status}: ${url}`);
|
|
199
|
+
}
|
|
200
|
+
const targets = await resp.json();
|
|
201
|
+
return targets;
|
|
202
|
+
}
|
|
203
|
+
async function killChrome(child, tmpDir) {
|
|
204
|
+
if (child.exitCode !== null) {
|
|
205
|
+
if (tmpDir) cleanupTmpDir(tmpDir);
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
return new Promise((resolve) => {
|
|
209
|
+
const timer = setTimeout(() => {
|
|
210
|
+
try {
|
|
211
|
+
child.kill("SIGKILL");
|
|
212
|
+
} catch {
|
|
213
|
+
}
|
|
214
|
+
if (tmpDir) cleanupTmpDir(tmpDir);
|
|
215
|
+
resolve();
|
|
216
|
+
}, 5e3);
|
|
217
|
+
child.once("exit", () => {
|
|
218
|
+
clearTimeout(timer);
|
|
219
|
+
if (tmpDir) cleanupTmpDir(tmpDir);
|
|
220
|
+
resolve();
|
|
221
|
+
});
|
|
222
|
+
try {
|
|
223
|
+
child.kill("SIGTERM");
|
|
224
|
+
} catch {
|
|
225
|
+
clearTimeout(timer);
|
|
226
|
+
if (tmpDir) cleanupTmpDir(tmpDir);
|
|
227
|
+
resolve();
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
function cleanupTmpDir(dir) {
|
|
232
|
+
try {
|
|
233
|
+
const { rmSync } = __require("fs");
|
|
234
|
+
rmSync(dir, { recursive: true, force: true });
|
|
235
|
+
} catch {
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
function sleep(ms) {
|
|
239
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
export {
|
|
243
|
+
DEFAULT_ARGS,
|
|
244
|
+
ANTI_DETECT_ARGS,
|
|
245
|
+
findChrome,
|
|
246
|
+
launchChrome,
|
|
247
|
+
connectToCDP,
|
|
248
|
+
getCDPTargets,
|
|
249
|
+
killChrome
|
|
250
|
+
};
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import {
|
|
2
|
+
launch
|
|
3
|
+
} from "./chunk-42RPMJ76.js";
|
|
1
4
|
import {
|
|
2
5
|
CDPInterceptorProxy
|
|
3
6
|
} from "./chunk-ZZ2TFWIV.js";
|
|
@@ -7,7 +10,6 @@ import { randomUUID } from "crypto";
|
|
|
7
10
|
import { existsSync, mkdirSync, readFileSync, readdirSync, unlinkSync, writeFileSync } from "fs";
|
|
8
11
|
import { join } from "path";
|
|
9
12
|
import { homedir } from "os";
|
|
10
|
-
import { chromium } from "playwright";
|
|
11
13
|
|
|
12
14
|
// src/utils/cdp.ts
|
|
13
15
|
async function fetchNoProxy(url) {
|
|
@@ -192,15 +194,18 @@ async function createBrowser(options) {
|
|
|
192
194
|
const realEndpoint = await resolveCDPEndpoint(options.cdpEndpoint);
|
|
193
195
|
if (options.intercept) {
|
|
194
196
|
const config = typeof options.intercept === "object" ? { ...options.intercept, cdpEndpoint: realEndpoint } : { cdpEndpoint: realEndpoint };
|
|
195
|
-
|
|
196
|
-
const proxyPort = await
|
|
197
|
+
_sharedCdpProxy = new CDPInterceptorProxy(config);
|
|
198
|
+
const proxyPort = await _sharedCdpProxy.start();
|
|
197
199
|
console.error(`[CDP Interceptor] Proxy running on ws://localhost:${proxyPort}, forwarding to ${realEndpoint}`);
|
|
198
|
-
|
|
200
|
+
const { browser: browser3 } = await launch({ cdpEndpoint: `ws://localhost:${proxyPort}` });
|
|
201
|
+
return browser3;
|
|
199
202
|
}
|
|
200
|
-
|
|
203
|
+
const { browser: browser2 } = await launch({ cdpEndpoint: realEndpoint });
|
|
204
|
+
return browser2;
|
|
201
205
|
}
|
|
202
206
|
const executablePath = options?.executablePath || process.env.XBROWSER_CHROMIUM_PATH || discoverChromiumPath();
|
|
203
|
-
|
|
207
|
+
const { browser } = await launch({ executablePath, headless: options?.headless ?? true });
|
|
208
|
+
return browser;
|
|
204
209
|
}
|
|
205
210
|
async function getBrowser(options) {
|
|
206
211
|
if (_sharedBrowser) return _sharedBrowser;
|
|
@@ -351,7 +356,7 @@ async function findOrRestoreSession(name, cdpEndpoint) {
|
|
|
351
356
|
async function createEphemeralContext(options) {
|
|
352
357
|
if (options?.cdpEndpoint) {
|
|
353
358
|
const endpoint = await resolveCDPEndpoint(options.cdpEndpoint);
|
|
354
|
-
const b2 = await
|
|
359
|
+
const { browser: b2 } = await launch({ cdpEndpoint: endpoint });
|
|
355
360
|
const contexts = b2.contexts();
|
|
356
361
|
const ctx = contexts[0] || await b2.newContext();
|
|
357
362
|
const page2 = await ctx.newPage();
|
|
@@ -391,33 +396,54 @@ function getAllSessions() {
|
|
|
391
396
|
async function installNetworkCapture(page, sessionName) {
|
|
392
397
|
if (process.env.XBROWSER_DAEMON_WORKER !== "1") return;
|
|
393
398
|
const { networkStore } = await import("./network-store-BN6QEZ7R.js");
|
|
394
|
-
|
|
399
|
+
const requestData = /* @__PURE__ */ new Map();
|
|
400
|
+
const responseMeta = /* @__PURE__ */ new Map();
|
|
401
|
+
const xbPage = page;
|
|
402
|
+
xbPage.on("request", (params) => {
|
|
395
403
|
try {
|
|
396
|
-
const
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
404
|
+
const p = params;
|
|
405
|
+
requestData.set(p.requestId, {
|
|
406
|
+
method: p.request.method,
|
|
407
|
+
headers: p.request.headers,
|
|
408
|
+
postData: p.request.postData ?? null,
|
|
409
|
+
resourceType: p.type
|
|
410
|
+
});
|
|
411
|
+
} catch {
|
|
412
|
+
}
|
|
413
|
+
});
|
|
414
|
+
xbPage.on("response", (params) => {
|
|
415
|
+
try {
|
|
416
|
+
const p = params;
|
|
417
|
+
responseMeta.set(p.requestId, {
|
|
418
|
+
status: p.response.status,
|
|
419
|
+
url: p.response.url,
|
|
420
|
+
headers: p.response.headers,
|
|
421
|
+
mimeType: p.response.mimeType,
|
|
422
|
+
type: p.type
|
|
423
|
+
});
|
|
424
|
+
} catch {
|
|
425
|
+
}
|
|
426
|
+
});
|
|
427
|
+
xbPage.on("requestfinished", async (params) => {
|
|
428
|
+
try {
|
|
429
|
+
const p = params;
|
|
430
|
+
const meta = responseMeta.get(p.requestId);
|
|
431
|
+
if (!meta) return;
|
|
432
|
+
const req = requestData.get(p.requestId);
|
|
433
|
+
const method = req?.method ?? "GET";
|
|
434
|
+
const contentType = meta.headers["content-type"] || meta.headers["Content-Type"] || "";
|
|
435
|
+
const resourceType = req?.resourceType ?? meta.type;
|
|
436
|
+
const requestHeaders = req?.headers ?? {};
|
|
407
437
|
let requestBody = void 0;
|
|
408
|
-
const method = request.method();
|
|
409
438
|
const isPostLike = ["POST", "PATCH", "PUT"].includes(method);
|
|
410
439
|
if (isPostLike && requestHeaders["content-type"]?.includes("application/json")) {
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
requestBody = postData;
|
|
418
|
-
}
|
|
440
|
+
const postData = req?.postData;
|
|
441
|
+
if (postData) {
|
|
442
|
+
try {
|
|
443
|
+
requestBody = JSON.parse(postData);
|
|
444
|
+
} catch {
|
|
445
|
+
requestBody = postData;
|
|
419
446
|
}
|
|
420
|
-
} catch {
|
|
421
447
|
}
|
|
422
448
|
}
|
|
423
449
|
let responseBody = void 0;
|
|
@@ -425,7 +451,11 @@ async function installNetworkCapture(page, sessionName) {
|
|
|
425
451
|
const isJsonish = contentType.includes("json") || contentType.includes("javascript") || contentType.includes("text/");
|
|
426
452
|
if (isJsonish) {
|
|
427
453
|
try {
|
|
428
|
-
const
|
|
454
|
+
const bodyResult = await xbPage._cdpSend(
|
|
455
|
+
"Network.getResponseBody",
|
|
456
|
+
{ requestId: p.requestId }
|
|
457
|
+
);
|
|
458
|
+
const text = bodyResult.body ?? "";
|
|
429
459
|
size = text.length;
|
|
430
460
|
if (size <= 10240) {
|
|
431
461
|
try {
|
|
@@ -438,8 +468,11 @@ async function installNetworkCapture(page, sessionName) {
|
|
|
438
468
|
}
|
|
439
469
|
} else {
|
|
440
470
|
try {
|
|
441
|
-
const
|
|
442
|
-
|
|
471
|
+
const bodyResult = await xbPage._cdpSend(
|
|
472
|
+
"Network.getResponseBody",
|
|
473
|
+
{ requestId: p.requestId }
|
|
474
|
+
);
|
|
475
|
+
size = bodyResult.body?.length ?? 0;
|
|
443
476
|
} catch {
|
|
444
477
|
size = 0;
|
|
445
478
|
}
|
|
@@ -447,17 +480,19 @@ async function installNetworkCapture(page, sessionName) {
|
|
|
447
480
|
networkStore.add(sessionName, {
|
|
448
481
|
timestamp: Date.now(),
|
|
449
482
|
method,
|
|
450
|
-
url,
|
|
451
|
-
path: new URL(url).pathname,
|
|
452
|
-
status:
|
|
483
|
+
url: meta.url,
|
|
484
|
+
path: new URL(meta.url).pathname,
|
|
485
|
+
status: meta.status,
|
|
453
486
|
contentType,
|
|
454
487
|
size,
|
|
455
|
-
headers,
|
|
488
|
+
headers: meta.headers,
|
|
456
489
|
body: responseBody,
|
|
457
490
|
requestHeaders,
|
|
458
491
|
requestBody,
|
|
459
|
-
resourceType
|
|
492
|
+
resourceType
|
|
460
493
|
});
|
|
494
|
+
requestData.delete(p.requestId);
|
|
495
|
+
responseMeta.delete(p.requestId);
|
|
461
496
|
} catch {
|
|
462
497
|
}
|
|
463
498
|
});
|
|
@@ -570,7 +605,7 @@ async function closeSessionByName(name) {
|
|
|
570
605
|
} catch {
|
|
571
606
|
}
|
|
572
607
|
try {
|
|
573
|
-
const { SessionRecorder } = await import("./session-recorder-
|
|
608
|
+
const { SessionRecorder } = await import("./session-recorder-MA75PKTQ.js");
|
|
574
609
|
SessionRecorder.cleanup(session.name);
|
|
575
610
|
} catch {
|
|
576
611
|
}
|