mirror of
https://github.com/morluto/rea.git
synced 2026-10-29 02:45:58 +00:00
Decode base64 JSON body bytes at the shape owner without replacement characters. Keep incomplete request correspondence unknown and use explicitly complete authored inventories for positive comparison controls. Repair semantic truncation and storage fixtures to satisfy their owning contracts without weakening assertions.
88 lines
2.8 KiB
TypeScript
88 lines
2.8 KiB
TypeScript
import { inferJsonShape, type JsonShape } from "../domain/jsonShape.js";
|
|
import { decodePaddedBase64 } from "../domain/paddedBase64.js";
|
|
import {
|
|
recordValue,
|
|
cdpStringValue,
|
|
type UnknownRecord,
|
|
} from "./CdpCaptureValues.js";
|
|
import { isJsonContentType } from "./CdpCaptureEventHelpers.js";
|
|
import type { CdpCaptureEventsState } from "./CdpCaptureEventState.js";
|
|
import type { NetworkState } from "./CdpCaptureEventTypes.js";
|
|
|
|
export const ingestResponseBodyShape = (
|
|
state: CdpCaptureEventsState,
|
|
requestId: string,
|
|
value: unknown,
|
|
): void => {
|
|
const result = recordValue(value);
|
|
const body = cdpStringValue(result?.body);
|
|
const base64Encoded = result?.base64Encoded;
|
|
if (body === undefined || typeof base64Encoded !== "boolean") {
|
|
invalidResponseBodyShape(state, requestId);
|
|
return;
|
|
}
|
|
const decoded = base64Encoded ? decodePaddedBase64(body) : body;
|
|
if (decoded === undefined) {
|
|
invalidResponseBodyShape(state, requestId);
|
|
return;
|
|
}
|
|
const shape = inferJsonShape(decoded);
|
|
if (shape === null) state.completeness.unavailable("json_body_shapes");
|
|
updateResponseBodyShape(state, requestId, shape);
|
|
};
|
|
|
|
export const requestBodyShape = (
|
|
state: CdpCaptureEventsState,
|
|
requestId: string,
|
|
request: UnknownRecord,
|
|
): NetworkState["body_shapes"] => {
|
|
state.missingRequestBodyShapeIds.delete(requestId);
|
|
if (!state.input.include_json_body_shapes)
|
|
return { status: "not_approved", request: null, response: null };
|
|
const headers = recordValue(request.headers);
|
|
const json = isJsonContentType(headers);
|
|
const body = cdpStringValue(request.postData);
|
|
// CDP may omit a long body from postData while reporting hasPostData.
|
|
const shape = json && body !== undefined ? inferJsonShape(body) : null;
|
|
const expected = json && (body !== undefined || request.hasPostData === true);
|
|
if (expected && shape === null) {
|
|
state.missingRequestBodyShapeIds.add(requestId);
|
|
state.completeness.unavailable("json_body_shapes");
|
|
}
|
|
return {
|
|
status: shape === null ? "unavailable" : "included",
|
|
request: shape,
|
|
response: null,
|
|
};
|
|
};
|
|
|
|
export const updateResponseBodyShape = (
|
|
state: CdpCaptureEventsState,
|
|
requestId: string,
|
|
response: JsonShape | null,
|
|
): void => {
|
|
const current = state.network.get(requestId);
|
|
if (current === undefined) return;
|
|
const request = current.body_shapes.request;
|
|
const status =
|
|
response !== null
|
|
? state.missingRequestBodyShapeIds.has(requestId)
|
|
? "partial"
|
|
: "included"
|
|
: request !== null
|
|
? "partial"
|
|
: "unavailable";
|
|
state.network.set(requestId, {
|
|
...current,
|
|
body_shapes: { status, request, response },
|
|
});
|
|
};
|
|
|
|
const invalidResponseBodyShape = (
|
|
state: CdpCaptureEventsState,
|
|
requestId: string,
|
|
): void => {
|
|
updateResponseBodyShape(state, requestId, null);
|
|
state.completeness.exclude("json_body_shapes", "invalid_protocol_value");
|
|
};
|