personal-agent-benchmark 0.1.0 → 0.2.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/README.md +2 -2
- package/dist/src/core/audit.d.ts +4 -2
- package/dist/src/core/audit.js +6 -2
- package/dist/src/core/audit.js.map +1 -1
- package/dist/src/core/types.d.ts +2 -0
- package/dist/src/core/warc.d.ts +14 -0
- package/dist/src/core/warc.js +65 -46
- package/dist/src/core/warc.js.map +1 -1
- package/dist/src/replay/whistle-plugin.d.ts +1 -1
- package/dist/src/replay/whistle-plugin.js +17 -0
- package/dist/src/replay/whistle-plugin.js.map +1 -1
- package/docs/bundle-format.md +4 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -86,13 +86,13 @@ The replay engine, the recording format and the `pab` command are published to n
|
|
|
86
86
|
`personal-agent-benchmark`; tasks are not part of the package.
|
|
87
87
|
|
|
88
88
|
```bash
|
|
89
|
-
npm install personal-agent-benchmark@0.
|
|
89
|
+
npm install personal-agent-benchmark@0.2.0
|
|
90
90
|
npx pab replay path/to/tasks/<id>
|
|
91
91
|
```
|
|
92
92
|
|
|
93
93
|
Modules are imported by path, for example `personal-agent-benchmark/scoring` or
|
|
94
94
|
`personal-agent-benchmark/core/rules`; `exports` in `package.json` lists them. While the version
|
|
95
|
-
is 0.x, a new minor version may change them. 0.1.x
|
|
95
|
+
is 0.x, a new minor version may change them. 0.1.x and 0.2.x read and write recordings in format 2
|
|
96
96
|
([docs/bundle-format.md](docs/bundle-format.md)); a new format comes with a new minor version.
|
|
97
97
|
|
|
98
98
|
## Tasks
|
package/dist/src/core/audit.d.ts
CHANGED
|
@@ -6,8 +6,10 @@ export interface AuditFinding {
|
|
|
6
6
|
}
|
|
7
7
|
/**
|
|
8
8
|
* Checks that a bundle is safe to publish: no credentials in stored requests, no live cookie
|
|
9
|
-
* values in stored responses, no
|
|
10
|
-
*
|
|
9
|
+
* values in stored responses, no stored header lines that are not headers (a header sent several
|
|
10
|
+
* times stored as one value joined by newlines hides every cookie after the first from the cookie
|
|
11
|
+
* check), no pages the rules exclude (bot checks), and nothing in the manifest beyond what replay
|
|
12
|
+
* reads (such as who recorded it).
|
|
11
13
|
* Returns one finding per problem; an empty list means the bundle passed.
|
|
12
14
|
*/
|
|
13
15
|
export declare function auditBundle(bundle: Bundle, rules: RuleSet): Promise<AuditFinding[]>;
|
package/dist/src/core/audit.js
CHANGED
|
@@ -42,8 +42,10 @@ const LEGACY_MANIFEST_KEYS = ['start_url'];
|
|
|
42
42
|
const CREDENTIAL_REQUEST_HEADERS = ['cookie', 'authorization', 'proxy-authorization', 'x-amz-access-token'];
|
|
43
43
|
/**
|
|
44
44
|
* Checks that a bundle is safe to publish: no credentials in stored requests, no live cookie
|
|
45
|
-
* values in stored responses, no
|
|
46
|
-
*
|
|
45
|
+
* values in stored responses, no stored header lines that are not headers (a header sent several
|
|
46
|
+
* times stored as one value joined by newlines hides every cookie after the first from the cookie
|
|
47
|
+
* check), no pages the rules exclude (bot checks), and nothing in the manifest beyond what replay
|
|
48
|
+
* reads (such as who recorded it).
|
|
47
49
|
* Returns one finding per problem; an empty list means the bundle passed.
|
|
48
50
|
*/
|
|
49
51
|
async function auditBundle(bundle, rules) {
|
|
@@ -66,6 +68,8 @@ async function auditBundle(bundle, rules) {
|
|
|
66
68
|
if (CREDENTIAL_REQUEST_HEADERS.includes(name.toLowerCase()))
|
|
67
69
|
add('request-credentials', `${name} header on ${ex.method} ${ex.url}`);
|
|
68
70
|
}
|
|
71
|
+
if (ex.malformedHeaderLines)
|
|
72
|
+
add('header-lines', `${ex.malformedHeaderLines} stored header lines are not headers (values joined by newlines?) on ${ex.method} ${ex.url}`);
|
|
69
73
|
for (const [name, value] of ex.respHeaders) {
|
|
70
74
|
if (name.toLowerCase() !== 'set-cookie')
|
|
71
75
|
continue;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit.js","sourceRoot":"","sources":["../../../src/core/audit.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,MAAY,EAAE,oCAAgB;AAI9B,iCAAuC;AAOvC,MAAM,aAAa,GAAa,CAAC,SAAS,EAAE,eAAe,EAAE,aAAa,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,CAA8B,CAAC;AACtJ,oGAAoG;AACpG,MAAM,oBAAoB,GAAG,CAAC,WAAW,CAAC,CAAC;AAC3C,MAAM,0BAA0B,GAAG,CAAC,QAAQ,EAAE,eAAe,EAAE,qBAAqB,EAAE,oBAAoB,CAAC,CAAC;AAE5G
|
|
1
|
+
{"version":3,"file":"audit.js","sourceRoot":"","sources":["../../../src/core/audit.ts"],"names":[],"mappings":"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"}
|
package/dist/src/core/types.d.ts
CHANGED
|
@@ -15,6 +15,8 @@ export interface Exchange {
|
|
|
15
15
|
/** Content-Encoding the site used on the wire; the stored body is already decoded. */
|
|
16
16
|
originalContentEncoding?: string;
|
|
17
17
|
resourceType?: string;
|
|
18
|
+
/** Read from a WARC: stored header lines of the request and response that are not headers (see parseHeaderLines). */
|
|
19
|
+
malformedHeaderLines?: number;
|
|
18
20
|
}
|
|
19
21
|
/** Index row for one exchange inside a bundle (indexes/entries.jsonl). */
|
|
20
22
|
export interface Entry {
|
package/dist/src/core/warc.d.ts
CHANGED
|
@@ -29,12 +29,26 @@ export declare class WarcWriter {
|
|
|
29
29
|
close(): void;
|
|
30
30
|
private write;
|
|
31
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Header lines as stored, as a header list. Recorders before record-replay 0.5.5 kept a header the
|
|
34
|
+
* site sent several times (Set-Cookie above all) as one value joined by newlines, as DevTools
|
|
35
|
+
* reports it, and wrote it that way: each further value is a line of its own after the header's
|
|
36
|
+
* line, ended by a bare newline, or by CRLF once the recording was rewritten. A line that is not a
|
|
37
|
+
* header is taken as a further value of the header before it; `malformed` counts those lines (lines
|
|
38
|
+
* before any header are left out).
|
|
39
|
+
*/
|
|
40
|
+
export declare function parseHeaderLines(lines: string[]): {
|
|
41
|
+
headers: HeaderList;
|
|
42
|
+
malformed: number;
|
|
43
|
+
};
|
|
32
44
|
/** Reads one record (plain or gzip member) at a known offset and returns its HTTP status, headers and payload. */
|
|
33
45
|
export declare function readResponseAt(file: string, span: Span): Promise<StoredResponse & {
|
|
34
46
|
type: string;
|
|
47
|
+
malformedHeaderLines: number;
|
|
35
48
|
}>;
|
|
36
49
|
export declare function readRequestAt(file: string, span: Span): Promise<{
|
|
37
50
|
headers: HeaderList;
|
|
51
|
+
malformedHeaderLines: number;
|
|
38
52
|
body: Buffer;
|
|
39
53
|
}>;
|
|
40
54
|
/** Iterates request/response pairs of any WARC (e.g. from ArchiveWeb.page) as exchanges. */
|
package/dist/src/core/warc.js
CHANGED
|
@@ -34,6 +34,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.WarcWriter = void 0;
|
|
37
|
+
exports.parseHeaderLines = parseHeaderLines;
|
|
37
38
|
exports.readResponseAt = readResponseAt;
|
|
38
39
|
exports.readRequestAt = readRequestAt;
|
|
39
40
|
exports.readExchanges = readExchanges;
|
|
@@ -127,47 +128,66 @@ class WarcWriter {
|
|
|
127
128
|
}
|
|
128
129
|
}
|
|
129
130
|
exports.WarcWriter = WarcWriter;
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
131
|
+
const HEADER_NAME = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
|
|
132
|
+
const CRLFCRLF = Buffer.from('\r\n\r\n');
|
|
133
|
+
/**
|
|
134
|
+
* Header lines as stored, as a header list. Recorders before record-replay 0.5.5 kept a header the
|
|
135
|
+
* site sent several times (Set-Cookie above all) as one value joined by newlines, as DevTools
|
|
136
|
+
* reports it, and wrote it that way: each further value is a line of its own after the header's
|
|
137
|
+
* line, ended by a bare newline, or by CRLF once the recording was rewritten. A line that is not a
|
|
138
|
+
* header is taken as a further value of the header before it; `malformed` counts those lines (lines
|
|
139
|
+
* before any header are left out).
|
|
140
|
+
*/
|
|
141
|
+
function parseHeaderLines(lines) {
|
|
142
|
+
const headers = [];
|
|
143
|
+
let malformed = 0;
|
|
144
|
+
let last;
|
|
145
|
+
for (const line of lines) {
|
|
146
|
+
// values joined to a line by bare newlines are never headers of their own
|
|
147
|
+
for (const [i, part] of line.split(/\r?\n|\r/).entries()) {
|
|
148
|
+
const colon = part.indexOf(':');
|
|
149
|
+
const name = colon > 0 ? part.slice(0, colon) : '';
|
|
150
|
+
if (i === 0 && HEADER_NAME.test(name)) {
|
|
151
|
+
headers.push([name, part.slice(colon + 1).trim()]);
|
|
152
|
+
last = name;
|
|
141
153
|
continue;
|
|
142
154
|
}
|
|
155
|
+
malformed++;
|
|
156
|
+
if (last && part.trim())
|
|
157
|
+
headers.push([last, part.trim()]);
|
|
143
158
|
}
|
|
144
|
-
out.push([k, v]);
|
|
145
159
|
}
|
|
146
|
-
return
|
|
160
|
+
return { headers, malformed };
|
|
147
161
|
}
|
|
148
|
-
/**
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
162
|
+
/**
|
|
163
|
+
* The HTTP message stored in a record, read by its bytes: warcio's own parsing drops header lines
|
|
164
|
+
* without a colon, so a malformed header could be neither repaired nor seen.
|
|
165
|
+
*/
|
|
166
|
+
function httpMessage(content) {
|
|
167
|
+
const end = content.indexOf(CRLFCRLF);
|
|
168
|
+
const [startLine = '', ...lines] = (end < 0 ? content : content.subarray(0, end)).toString('utf8').split('\r\n');
|
|
169
|
+
const { headers, malformed } = parseHeaderLines(lines.filter(Boolean));
|
|
170
|
+
return { startLine, headers, malformedHeaderLines: malformed, body: end < 0 ? Buffer.alloc(0) : content.subarray(end + 4) };
|
|
171
|
+
}
|
|
172
|
+
/** Status of a stored response; a request that got no response is stored with status -1. */
|
|
173
|
+
function statusOf(startLine) {
|
|
174
|
+
const m = /^HTTP\/\S+ (-?\d+) ?(.*)$/.exec(startLine);
|
|
175
|
+
return m ? { status: Number(m[1]), statusText: m[2] } : { status: 200, statusText: '' };
|
|
176
|
+
}
|
|
177
|
+
async function readRecordAt(file, span) {
|
|
178
|
+
const record = await warcio_1.WARCParser.parse([readSpan(file, span)], { keepHeadersCase: true, parseHttp: false });
|
|
152
179
|
if (!record)
|
|
153
180
|
throw new Error(`no WARC record at ${file}:${span.offset}`);
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
headers: headerList(record),
|
|
161
|
-
body,
|
|
162
|
-
};
|
|
181
|
+
return { type: record.warcType ?? '', http: httpMessage(Buffer.from(await record.readFully(false))) };
|
|
182
|
+
}
|
|
183
|
+
/** Reads one record (plain or gzip member) at a known offset and returns its HTTP status, headers and payload. */
|
|
184
|
+
async function readResponseAt(file, span) {
|
|
185
|
+
const { type, http } = await readRecordAt(file, span);
|
|
186
|
+
return { type, ...statusOf(http.startLine), headers: http.headers, malformedHeaderLines: http.malformedHeaderLines, body: http.body };
|
|
163
187
|
}
|
|
164
188
|
async function readRequestAt(file, span) {
|
|
165
|
-
const
|
|
166
|
-
|
|
167
|
-
if (!record)
|
|
168
|
-
throw new Error(`no WARC record at ${file}:${span.offset}`);
|
|
169
|
-
const body = Buffer.from(await record.readFully(false));
|
|
170
|
-
return { headers: headerList(record), body };
|
|
189
|
+
const { http } = await readRecordAt(file, span);
|
|
190
|
+
return { headers: http.headers, malformedHeaderLines: http.malformedHeaderLines, body: http.body };
|
|
171
191
|
}
|
|
172
192
|
function readSpan(file, span) {
|
|
173
193
|
const fd = fs.openSync(file, 'r');
|
|
@@ -184,17 +204,14 @@ function readSpan(file, span) {
|
|
|
184
204
|
async function* readExchanges(file) {
|
|
185
205
|
const stream = fs.createReadStream(file);
|
|
186
206
|
let n = 0;
|
|
187
|
-
const parser = new warcio_1.WARCParser(stream, { keepHeadersCase: true });
|
|
207
|
+
const parser = new warcio_1.WARCParser(stream, { keepHeadersCase: true, parseHttp: false });
|
|
188
208
|
const responses = [];
|
|
189
209
|
const byRespId = new Map();
|
|
190
210
|
const requests = [];
|
|
191
211
|
for await (const record of parser) {
|
|
192
212
|
const type = record.warcType;
|
|
193
213
|
if (type === 'response' || type === 'revisit') {
|
|
194
|
-
const
|
|
195
|
-
const body = type === 'response' ? Buffer.from(await record.readFully(false)) : Buffer.alloc(0);
|
|
196
|
-
const headers = headerList(record);
|
|
197
|
-
const enc = (0, util_1.header)(headers, 'content-encoding');
|
|
214
|
+
const http = httpMessage(Buffer.from(await record.readFully(false)));
|
|
198
215
|
const ex = {
|
|
199
216
|
id: `w${n++}`,
|
|
200
217
|
ts: record.warcDate ?? new Date().toISOString(),
|
|
@@ -202,23 +219,24 @@ async function* readExchanges(file) {
|
|
|
202
219
|
url: record.warcTargetURI ?? '',
|
|
203
220
|
httpVersion: 'HTTP/1.1',
|
|
204
221
|
reqHeaders: [],
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
222
|
+
...statusOf(http.startLine),
|
|
223
|
+
respHeaders: http.headers,
|
|
224
|
+
respBody: type === 'response' ? http.body : Buffer.alloc(0),
|
|
225
|
+
originalContentEncoding: (0, util_1.header)(http.headers, 'content-encoding'),
|
|
226
|
+
malformedHeaderLines: http.malformedHeaderLines,
|
|
210
227
|
};
|
|
211
228
|
responses.push(ex);
|
|
212
229
|
byRespId.set(record.warcHeader('WARC-Record-ID') ?? '', ex);
|
|
213
230
|
}
|
|
214
231
|
else if (type === 'request') {
|
|
215
|
-
const
|
|
232
|
+
const http = httpMessage(Buffer.from(await record.readFully(false)));
|
|
216
233
|
requests.push({
|
|
217
234
|
concurrentTo: record.warcHeader('WARC-Concurrent-To') ?? undefined,
|
|
218
235
|
url: record.warcTargetURI ?? '',
|
|
219
|
-
method:
|
|
220
|
-
headers:
|
|
221
|
-
|
|
236
|
+
method: http.startLine.split(' ')[0] || 'GET',
|
|
237
|
+
headers: http.headers,
|
|
238
|
+
malformedHeaderLines: http.malformedHeaderLines,
|
|
239
|
+
body: http.body,
|
|
222
240
|
});
|
|
223
241
|
}
|
|
224
242
|
else {
|
|
@@ -231,6 +249,7 @@ async function* readExchanges(file) {
|
|
|
231
249
|
continue;
|
|
232
250
|
ex.method = r.method.toUpperCase();
|
|
233
251
|
ex.reqHeaders = r.headers;
|
|
252
|
+
ex.malformedHeaderLines = (ex.malformedHeaderLines ?? 0) + r.malformedHeaderLines;
|
|
234
253
|
ex.reqBody = r.body.length ? r.body : undefined;
|
|
235
254
|
}
|
|
236
255
|
for (const ex of responses)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"warc.js","sourceRoot":"","sources":["../../../src/core/warc.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"warc.js","sourceRoot":"","sources":["../../../src/core/warc.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,MAAY,EAAE,oCAAgB;AAC9B,MAAY,IAAI,sCAAkB;AAClC,yCAAyC;AACzC,mCAAgE;AAEhE,iCAAgC;AAOhC,MAAM,eAAe,GAAG,kEAAkE,CAAC;AAE3F;;;;GAIG;AACH;IAIuB,IAAI;IAA2B,IAAI;IAHvC,EAAE,CAAS;IACpB,MAAM,GAAG,CAAC,CAAC;IAEnB,YAAqB,IAAY,EAAmB,IAAI,GAAuB,EAAE;oBAA5D,IAAI;oBAA2B,IAAI;QACtD,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACtD,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACnC,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,IAA4B;QAC1C,MAAM,MAAM,GAAG,mBAAU,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,WAAW,EAAE,UAAU,EAAE,EAAE,IAAI,CAAC,CAAC;QAChH,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC5B,CAAC;IAED,iGAAiG;IACjG,KAAK,CAAC,aAAa,CAAC,EAAY,EAAE,OAAuD;QACvF,MAAM,UAAU,GAAG,YAAY,EAAE,CAAC,MAAM,IAAI,EAAE,CAAC,UAAU,IAAI,wBAAY,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC;QACpG,MAAM,WAAW,GAA2B,EAAE,gBAAgB,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;QACxE,IAAI,EAAE,CAAC,uBAAuB;YAAE,WAAW,CAAC,8BAA8B,CAAC,GAAG,EAAE,CAAC,uBAAuB,CAAC;QACzG,IAAI,EAAE,CAAC,YAAY;YAAE,WAAW,CAAC,kBAAkB,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC;QAEvE,IAAI,UAAsB,CAAC;QAC3B,IAAI,OAAO,EAAE,CAAC;YACZ,UAAU,GAAG,mBAAU,CAAC,MAAM,CAC5B;gBACE,GAAG,EAAE,EAAE,CAAC,GAAG;gBACX,IAAI,EAAE,EAAE,CAAC,EAAE;gBACX,IAAI,EAAE,SAAS;gBACf,WAAW,EAAE,UAAU;gBACvB,WAAW,EAAE,OAAO,CAAC,GAAG;gBACxB,YAAY,EAAE,OAAO,CAAC,IAAI;gBAC1B,WAAW,EAAE,EAAE,GAAG,WAAW,EAAE,cAAc,EAAE,eAAe,EAAE,mBAAmB,EAAE,OAAO,CAAC,MAAM,EAAE;gBACrG,WAAW,EAAE,EAAE,CAAC,WAAW;gBAC3B,UAAU;gBACV,eAAe,EAAE,IAAI;aACtB,EACD,EAAE,CACH,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,UAAU,GAAG,mBAAU,CAAC,MAAM,CAC5B;gBACE,GAAG,EAAE,EAAE,CAAC,GAAG;gBACX,IAAI,EAAE,EAAE,CAAC,EAAE;gBACX,IAAI,EAAE,UAAU;gBAChB,WAAW,EAAE,UAAU;gBACvB,WAAW;gBACX,WAAW,EAAE,EAAE,CAAC,WAAW;gBAC3B,UAAU;gBACV,eAAe,EAAE,IAAI;aACtB,EACD,CAAC,EAAE,CAAC,QAAQ,CAAC,CACd,CAAC;QACJ,CAAC;QACD,MAAM,MAAM,GAAG,UAAU,CAAC,UAAU,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC;QAC7D,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QAE1C,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;QAC1B,MAAM,UAAU,GAAe,IAAA,aAAM,EAAC,EAAE,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,CAAC;QACpH,MAAM,SAAS,GAAG,mBAAU,CAAC,MAAM,CACjC;YACE,GAAG,EAAE,EAAE,CAAC,GAAG;YACX,IAAI,EAAE,EAAE,CAAC,EAAE;YACX,IAAI,EAAE,SAAS;YACf,WAAW,EAAE,UAAU;YACvB,WAAW,EAAE,EAAE,oBAAoB,EAAE,MAAM,EAAE,gBAAgB,EAAE,EAAE,CAAC,EAAE,EAAE;YACtE,WAAW,EAAE,UAAU;YACvB,UAAU,EAAE,GAAG,EAAE,CAAC,MAAM,IAAI,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,MAAM,WAAW;YAC5D,eAAe,EAAE,IAAI;SACtB,EACD,EAAE,CAAC,OAAO,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CACpD,CAAC;QACF,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QACxC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;IACvB,CAAC;IAED,KAAK;QACH,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACxB,CAAC;IAEO,KAAK,CAAC,KAAK,CAAC,MAAkB;QACpC,MAAM,KAAK,GAAG,MAAM,uBAAc,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,KAAK,EAAE,CAAC,CAAC;QACxF,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;QAC7B,MAAM,IAAI,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC;QAC3D,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC;QAC5B,OAAO,IAAI,CAAC;IACd,CAAC;CACF;;AAED,MAAM,WAAW,GAAG,+BAA+B,CAAC;AACpD,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;AAEzC;;;;;;;GAOG;AACH,0BAAiC,KAAe;IAC9C,MAAM,OAAO,GAAe,EAAE,CAAC;IAC/B,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,IAAI,IAAwB,CAAC;IAC7B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,0EAA0E;QAC1E,KAAK,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC;YACzD,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YAChC,MAAM,IAAI,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACnD,IAAI,CAAC,KAAK,CAAC,IAAI,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBACtC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;gBACnD,IAAI,GAAG,IAAI,CAAC;gBACZ,SAAS;YACX,CAAC;YACD,SAAS,EAAE,CAAC;YACZ,IAAI,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE;gBAAE,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;AAChC,CAAC;AAWD;;;GAGG;AACH,SAAS,WAAW,CAAC,OAAe;IAClC,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACtC,MAAM,CAAC,SAAS,GAAG,EAAE,EAAE,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACjH,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,gBAAgB,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;IACvE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,oBAAoB,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,GAAG,CAAC,CAAC,EAAE,CAAC;AAC9H,CAAC;AAED,4FAA4F;AAC5F,SAAS,QAAQ,CAAC,SAAiB;IACjC,MAAM,CAAC,GAAG,2BAA2B,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACtD,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC;AAC1F,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,IAAY,EAAE,IAAU;IAClD,MAAM,MAAM,GAAG,MAAM,mBAAU,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;IAC3G,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,IAAI,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IACzE,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,QAAQ,IAAI,EAAE,EAAE,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;AACxG,CAAC;AAED,kHAAkH;AAC3G,KAAK,yBAAyB,IAAY,EAAE,IAAU;IAC3D,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACtD,OAAO,EAAE,IAAI,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,oBAAoB,EAAE,IAAI,CAAC,oBAAoB,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;AACxI,CAAC;AAEM,KAAK,wBAAwB,IAAY,EAAE,IAAU;IAC1D,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAChD,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,oBAAoB,EAAE,IAAI,CAAC,oBAAoB,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;AACrG,CAAC;AAED,SAAS,QAAQ,CAAC,IAAY,EAAE,IAAU;IACxC,MAAM,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAClC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACtC,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QAClD,OAAO,GAAG,CAAC;IACb,CAAC;YAAS,CAAC;QACT,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IACnB,CAAC;AACH,CAAC;AAED,4FAA4F;AACrF,KAAK,SAAS,CAAC,eAAe,IAAY;IAC/C,MAAM,MAAM,GAAG,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACzC,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,MAAM,MAAM,GAAG,IAAI,mBAAU,CAAC,MAAM,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;IACnF,MAAM,SAAS,GAAe,EAAE,CAAC;IACjC,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAoB,CAAC;IAC7C,MAAM,QAAQ,GAA8H,EAAE,CAAC;IAC/I,IAAI,KAAK,EAAE,MAAM,MAAM,IAAI,MAAM,EAAE,CAAC;QAClC,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC;QAC7B,IAAI,IAAI,KAAK,UAAU,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YAC9C,MAAM,IAAI,GAAG,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACrE,MAAM,EAAE,GAAa;gBACnB,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE;gBACb,EAAE,EAAE,MAAM,CAAC,QAAQ,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBAC/C,MAAM,EAAE,KAAK;gBACb,GAAG,EAAE,MAAM,CAAC,aAAa,IAAI,EAAE;gBAC/B,WAAW,EAAE,UAAU;gBACvB,UAAU,EAAE,EAAE;gBACd,GAAG,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC;gBAC3B,WAAW,EAAE,IAAI,CAAC,OAAO;gBACzB,QAAQ,EAAE,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;gBAC3D,uBAAuB,EAAE,IAAA,aAAM,EAAC,IAAI,CAAC,OAAO,EAAE,kBAAkB,CAAC;gBACjE,oBAAoB,EAAE,IAAI,CAAC,oBAAoB;aAChD,CAAC;YACF,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACnB,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,gBAAgB,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;QAC9D,CAAC;aAAM,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YAC9B,MAAM,IAAI,GAAG,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACrE,QAAQ,CAAC,IAAI,CAAC;gBACZ,YAAY,EAAE,MAAM,CAAC,UAAU,CAAC,oBAAoB,CAAC,IAAI,SAAS;gBAClE,GAAG,EAAE,MAAM,CAAC,aAAa,IAAI,EAAE;gBAC/B,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK;gBAC7C,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,oBAAoB,EAAE,IAAI,CAAC,oBAAoB;gBAC/C,IAAI,EAAE,IAAI,CAAC,IAAI;aAChB,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,MAAM,MAAM,CAAC,SAAS,EAAE,CAAC;QAC3B,CAAC;IACH,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,YAAY,IAAI,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC;QACnI,IAAI,CAAC,EAAE;YAAE,SAAS;QAClB,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;QACnC,EAAE,CAAC,UAAU,GAAG,CAAC,CAAC,OAAO,CAAC;QAC1B,EAAE,CAAC,oBAAoB,GAAG,CAAC,EAAE,CAAC,oBAAoB,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,oBAAoB,CAAC;QAClF,EAAE,CAAC,OAAO,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;IAClD,CAAC;IACD,KAAK,MAAM,EAAE,IAAI,SAAS;QAAE,MAAM,EAAE,CAAC;AACvC,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type IncomingMessage, type Server, type ServerResponse } from 'node:http';
|
|
2
2
|
/**
|
|
3
3
|
* whistle plugin entry (whistle.bench-replay). The only whistle rule is
|
|
4
4
|
* `/./ enable://capture bench-replay://`, so every request arrives here and is
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.handleWhistleRequest = handleWhistleRequest;
|
|
4
4
|
exports.server = server;
|
|
5
|
+
const node_http_1 = require("node:http");
|
|
5
6
|
const engine_1 = require("./engine");
|
|
6
7
|
let enginePromise;
|
|
7
8
|
function engine() {
|
|
@@ -31,9 +32,25 @@ function cleanHeaders(headers) {
|
|
|
31
32
|
}
|
|
32
33
|
return out;
|
|
33
34
|
}
|
|
35
|
+
/** Framing of the recorded connection; replay frames its own responses (Content-Length, no trailers). */
|
|
36
|
+
const FRAMING_HEADERS = new Set(['connection', 'keep-alive', 'proxy-connection', 'te', 'trailer', 'transfer-encoding', 'upgrade']);
|
|
37
|
+
/**
|
|
38
|
+
* Headers as Node sends them. Node refuses a whole response for one header it cannot send (a bad
|
|
39
|
+
* name, control characters, characters beyond Latin-1, a Trailer on a response with a length), so
|
|
40
|
+
* such a header is left out instead.
|
|
41
|
+
*/
|
|
34
42
|
function toNodeHeaders(list) {
|
|
35
43
|
const out = {};
|
|
36
44
|
for (const [k, v] of list) {
|
|
45
|
+
if (FRAMING_HEADERS.has(k.toLowerCase()))
|
|
46
|
+
continue;
|
|
47
|
+
try {
|
|
48
|
+
(0, node_http_1.validateHeaderName)(k);
|
|
49
|
+
(0, node_http_1.validateHeaderValue)(k, v);
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
37
54
|
const prev = out[k];
|
|
38
55
|
out[k] = prev === undefined ? v : Array.isArray(prev) ? [...prev, v] : [prev, v];
|
|
39
56
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"whistle-plugin.js","sourceRoot":"","sources":["../../../src/replay/whistle-plugin.ts"],"names":[],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"whistle-plugin.js","sourceRoot":"","sources":["../../../src/replay/whistle-plugin.ts"],"names":[],"mappings":"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"}
|
package/docs/bundle-format.md
CHANGED
|
@@ -90,6 +90,10 @@ Each exchange is two records: `response` (or `revisit`) first, then `request`, w
|
|
|
90
90
|
original.
|
|
91
91
|
- Requests carry no `Cookie` or `Authorization` header; every `Set-Cookie` value is `REDACTED`.
|
|
92
92
|
`pab audit` verifies both.
|
|
93
|
+
- Every header line is a header: a header sent several times is stored once per value. Recordings
|
|
94
|
+
made with record-replay before 0.5.5 stored such a header as one value joined by newlines, so
|
|
95
|
+
each further value is a line of its own; readers take those lines as values of the header on the
|
|
96
|
+
line before, and `pab audit` fails a bundle that has any.
|
|
93
97
|
- Custom WARC headers: `RR-Exchange-Id` (the id in `entries.jsonl`), `RR-Resource-Type`.
|
|
94
98
|
|
|
95
99
|
## entries.jsonl
|
package/package.json
CHANGED