@glubean/browser 0.1.2
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/chrome.d.ts +44 -0
- package/dist/chrome.d.ts.map +1 -0
- package/dist/chrome.js +134 -0
- package/dist/chrome.js.map +1 -0
- package/dist/index.d.ts +43 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +41 -0
- package/dist/index.js.map +1 -0
- package/dist/locator.d.ts +39 -0
- package/dist/locator.d.ts.map +1 -0
- package/dist/locator.js +116 -0
- package/dist/locator.js.map +1 -0
- package/dist/metrics.d.ts +23 -0
- package/dist/metrics.d.ts.map +1 -0
- package/dist/metrics.js +54 -0
- package/dist/metrics.js.map +1 -0
- package/dist/network.d.ts +55 -0
- package/dist/network.d.ts.map +1 -0
- package/dist/network.js +176 -0
- package/dist/network.js.map +1 -0
- package/dist/page.d.ts +543 -0
- package/dist/page.d.ts.map +1 -0
- package/dist/page.js +1259 -0
- package/dist/page.js.map +1 -0
- package/dist/plugin.d.ts +21 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +120 -0
- package/dist/plugin.js.map +1 -0
- package/package.json +33 -0
package/dist/network.js
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CDP Network domain listener for auto-tracing in-page requests.
|
|
3
|
+
*
|
|
4
|
+
* Intercepts XHR, fetch, and document requests inside the browser page and
|
|
5
|
+
* emits them as Glubean trace events so they appear in the same timeline as
|
|
6
|
+
* `ctx.http` calls.
|
|
7
|
+
*
|
|
8
|
+
* @module network
|
|
9
|
+
*/
|
|
10
|
+
const SKIP_PROTOCOLS = ["data:", "chrome-extension:", "devtools:", "blob:"];
|
|
11
|
+
/** Default content-type prefixes to include in traces. */
|
|
12
|
+
const DEFAULT_INCLUDE = ["application/json", "text/html"];
|
|
13
|
+
/** Default URL paths to skip (browser-initiated noise). */
|
|
14
|
+
const DEFAULT_EXCLUDE_PATHS = [
|
|
15
|
+
"/favicon.ico",
|
|
16
|
+
"/favicon.png",
|
|
17
|
+
"/apple-touch-icon.png",
|
|
18
|
+
"/apple-touch-icon-precomposed.png",
|
|
19
|
+
];
|
|
20
|
+
/** Max response body size to capture (bytes). Larger bodies are truncated. */
|
|
21
|
+
const MAX_BODY_BYTES = 64 * 1024;
|
|
22
|
+
/** @internal Exported for testing. */
|
|
23
|
+
export function shouldSkipProtocol(url) {
|
|
24
|
+
for (const proto of SKIP_PROTOCOLS) {
|
|
25
|
+
if (url.startsWith(proto))
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
/** @internal Exported for testing. */
|
|
31
|
+
export function shouldSkipPath(url, excludePaths) {
|
|
32
|
+
try {
|
|
33
|
+
const pathname = new URL(url).pathname;
|
|
34
|
+
for (const p of excludePaths) {
|
|
35
|
+
if (pathname === p)
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
// invalid URL, don't skip
|
|
41
|
+
}
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
/** @internal Exported for testing. */
|
|
45
|
+
export function shouldInclude(contentType, include) {
|
|
46
|
+
const ct = contentType.toLowerCase();
|
|
47
|
+
for (const prefix of include) {
|
|
48
|
+
if (ct.startsWith(prefix))
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Attach a CDP Network listener to the page that emits Glubean trace events
|
|
55
|
+
* for every in-page network request.
|
|
56
|
+
*
|
|
57
|
+
* Returns a cleanup function that detaches the listener.
|
|
58
|
+
*/
|
|
59
|
+
export async function attachNetworkTracer(page, options) {
|
|
60
|
+
const { trace, filter, include = DEFAULT_INCLUDE, excludePaths = DEFAULT_EXCLUDE_PATHS } = options;
|
|
61
|
+
const cdp = await page.createCDPSession();
|
|
62
|
+
await cdp.send("Network.enable");
|
|
63
|
+
const pending = new Map();
|
|
64
|
+
// ── requestWillBeSent: capture request info ─────────────────────────
|
|
65
|
+
const onRequestWillBeSent = (params) => {
|
|
66
|
+
pending.set(params.requestId, {
|
|
67
|
+
method: params.request.method,
|
|
68
|
+
url: params.request.url,
|
|
69
|
+
startMs: params.timestamp * 1000,
|
|
70
|
+
requestBody: params.request.postData,
|
|
71
|
+
});
|
|
72
|
+
};
|
|
73
|
+
// ── responseReceived: capture response metadata (body not yet ready) ─
|
|
74
|
+
const onResponseReceived = (params) => {
|
|
75
|
+
const req = pending.get(params.requestId);
|
|
76
|
+
if (!req)
|
|
77
|
+
return;
|
|
78
|
+
req.status = params.response.status;
|
|
79
|
+
req.contentType = params.response.mimeType || "";
|
|
80
|
+
req.responseTimestamp = params.timestamp;
|
|
81
|
+
};
|
|
82
|
+
// ── loadingFinished: body available, emit trace ─────────────────────
|
|
83
|
+
const onLoadingFinished = async (params) => {
|
|
84
|
+
const req = pending.get(params.requestId);
|
|
85
|
+
if (!req || req.status === undefined)
|
|
86
|
+
return;
|
|
87
|
+
pending.delete(params.requestId);
|
|
88
|
+
// Always skip non-HTTP protocols
|
|
89
|
+
if (shouldSkipProtocol(req.url))
|
|
90
|
+
return;
|
|
91
|
+
const contentType = req.contentType;
|
|
92
|
+
const status = req.status;
|
|
93
|
+
// Apply filter: custom predicate > default path + include checks
|
|
94
|
+
if (filter) {
|
|
95
|
+
if (!filter({ url: req.url, contentType, status }))
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
if (shouldSkipPath(req.url, excludePaths))
|
|
100
|
+
return;
|
|
101
|
+
if (!shouldInclude(contentType, include))
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
const duration = Math.round((req.responseTimestamp ?? params.timestamp) * 1000 - req.startMs);
|
|
105
|
+
// Always capture response body for traced requests. Body filtering
|
|
106
|
+
// and redaction happen downstream in the runner/CLI pipeline.
|
|
107
|
+
let responseBody;
|
|
108
|
+
try {
|
|
109
|
+
const result = await cdp.send("Network.getResponseBody", {
|
|
110
|
+
requestId: params.requestId,
|
|
111
|
+
});
|
|
112
|
+
if (!result.base64Encoded) {
|
|
113
|
+
const raw = result.body.length > MAX_BODY_BYTES
|
|
114
|
+
? result.body.slice(0, MAX_BODY_BYTES) + "…[truncated]"
|
|
115
|
+
: result.body;
|
|
116
|
+
try {
|
|
117
|
+
responseBody = JSON.parse(raw);
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
responseBody = raw;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
// Body not available (cached, redirected, etc.) — skip silently.
|
|
126
|
+
}
|
|
127
|
+
// Parse request body as JSON if possible.
|
|
128
|
+
let requestBody;
|
|
129
|
+
if (req.requestBody) {
|
|
130
|
+
try {
|
|
131
|
+
requestBody = JSON.parse(req.requestBody);
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
requestBody = req.requestBody;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
trace({
|
|
138
|
+
name: `[browser] ${req.method} ${shortPath(req.url)}`,
|
|
139
|
+
method: req.method,
|
|
140
|
+
url: req.url,
|
|
141
|
+
status,
|
|
142
|
+
duration,
|
|
143
|
+
...(requestBody !== undefined && { requestBody }),
|
|
144
|
+
...(responseBody !== undefined && { responseBody }),
|
|
145
|
+
});
|
|
146
|
+
};
|
|
147
|
+
const onLoadingFailed = (params) => {
|
|
148
|
+
pending.delete(params.requestId);
|
|
149
|
+
};
|
|
150
|
+
cdp.on("Network.requestWillBeSent", onRequestWillBeSent);
|
|
151
|
+
cdp.on("Network.responseReceived", onResponseReceived);
|
|
152
|
+
cdp.on("Network.loadingFinished", onLoadingFinished);
|
|
153
|
+
cdp.on("Network.loadingFailed", onLoadingFailed);
|
|
154
|
+
return async () => {
|
|
155
|
+
cdp.off("Network.requestWillBeSent", onRequestWillBeSent);
|
|
156
|
+
cdp.off("Network.responseReceived", onResponseReceived);
|
|
157
|
+
cdp.off("Network.loadingFinished", onLoadingFinished);
|
|
158
|
+
cdp.off("Network.loadingFailed", onLoadingFailed);
|
|
159
|
+
try {
|
|
160
|
+
await cdp.detach();
|
|
161
|
+
}
|
|
162
|
+
catch {
|
|
163
|
+
// page may already be closed
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
function shortPath(url) {
|
|
168
|
+
try {
|
|
169
|
+
const u = new URL(url);
|
|
170
|
+
return u.pathname + u.search;
|
|
171
|
+
}
|
|
172
|
+
catch {
|
|
173
|
+
return url;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
//# sourceMappingURL=network.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"network.js","sourceRoot":"","sources":["../src/network.ts"],"names":[],"mappings":"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"}
|