Include request body and response header info for fetch calls (#4)

This commit is contained in:
Brian Hackett 2025-01-14 16:17:47 -08:00 committed by GitHub
parent 6543f33d54
commit 80ce84f166
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -4,7 +4,7 @@ import { assert, stringToBase64, uint8ArrayToBase64 } from "./ReplayProtocolClie
export interface SimulationResource { export interface SimulationResource {
url: string; url: string;
requestBodyBase64?: string; requestBodyBase64: string;
responseBodyBase64?: string; responseBodyBase64?: string;
responseStatus?: number; responseStatus?: number;
responseHeaders?: Record<string, string>; responseHeaders?: Record<string, string>;
@ -130,14 +130,19 @@ function addRecordingMessageHandler(messageHandlerId: string) {
const startTime = Date.now(); const startTime = Date.now();
function addTextResource(path: string, text: string) { interface RequestInfo {
const url = (new URL(path, window.location.href)).href; url: string;
requestBody: string;
}
function addTextResource(info: RequestInfo, text: string, responseHeaders: Record<string, string>) {
const url = (new URL(info.url, window.location.href)).href;
resources.push({ resources.push({
url, url,
requestBodyBase64: "", requestBodyBase64: stringToBase64(info.requestBody),
responseBodyBase64: stringToBase64(text), responseBodyBase64: stringToBase64(text),
responseStatus: 200, responseStatus: 200,
responseHeaders: {}, responseHeaders,
}); });
} }
@ -388,26 +393,34 @@ function addRecordingMessageHandler(messageHandlerId: string) {
}), }),
}; };
// Map Response to the triggering URL before redirects. // Map Response to the info associated with the original request (before redirects).
const responseToURL = new WeakMap<Response, string>(); const responseToRequestInfo = new WeakMap<Response, RequestInfo>();
function convertHeaders(headers: Headers) {
const result: Record<string, string> = {};
headers.forEach((value, key) => {
result[key] = value;
});
return result;
}
const ResponseMethods = { const ResponseMethods = {
_name: "Response", _name: "Response",
json: (v: any, response: Response) => json: (v: any, response: Response) =>
createFunctionProxy(v, "json", async (promise: Promise<any>) => { createFunctionProxy(v, "json", async (promise: Promise<any>) => {
const json = await promise; const json = await promise;
const url = responseToURL.get(response); const requestInfo = responseToRequestInfo.get(response);
if (url) { if (requestInfo) {
addTextResource(url, JSON.stringify(json)); addTextResource(requestInfo, JSON.stringify(json), convertHeaders(response.headers));
} }
return json; return json;
}), }),
text: (v: any, response: Response) => text: (v: any, response: Response) =>
createFunctionProxy(v, "text", async (promise: Promise<any>) => { createFunctionProxy(v, "text", async (promise: Promise<any>) => {
const text = await promise; const text = await promise;
const url = responseToURL.get(response); const requestInfo = responseToRequestInfo.get(response);
if (url) { if (requestInfo) {
addTextResource(url, text); addTextResource(requestInfo, text, convertHeaders(response.headers));
} }
return text; return text;
}), }),
@ -474,13 +487,16 @@ function addRecordingMessageHandler(messageHandlerId: string) {
const baseFetch = window.fetch; const baseFetch = window.fetch;
window.fetch = async (info, options) => { window.fetch = async (info, options) => {
const url = info instanceof Request ? info.url : info.toString(); const url = info instanceof Request ? info.url : info.toString();
const requestBody = (typeof options?.body == "string") ? options.body : "";
const requestInfo: RequestInfo = { url, requestBody };
try { try {
const rv = await baseFetch(info, options); const rv = await baseFetch(info, options);
responseToURL.set(rv, url); responseToRequestInfo.set(rv, requestInfo);
return createProxy(rv); return createProxy(rv);
} catch (error) { } catch (error) {
resources.push({ resources.push({
url, url,
requestBodyBase64: stringToBase64(requestBody),
error: String(error), error: String(error),
}); });
throw error; throw error;