110 lines
3.4 KiB
TypeScript
110 lines
3.4 KiB
TypeScript
let requestMap = {}
|
|
|
|
export function resetMap() {
|
|
requestMap = {}
|
|
}
|
|
|
|
export async function attachDebuggerToTab(tabId: string | number) {
|
|
await new Promise((resolve, reject) => {
|
|
chrome.debugger.attach({ tabId }, "1.3", () => {
|
|
if (chrome.runtime.lastError)
|
|
return reject(chrome.runtime.lastError.message);
|
|
chrome.debugger.sendCommand({ tabId }, "Network.enable", {}, resolve);
|
|
});
|
|
chrome.debugger.onEvent.addListener(handleRequestIntercept);
|
|
});
|
|
}
|
|
export async function detachDebuggerFromTab(tabId: string) {
|
|
return new Promise((resolve, reject) => {
|
|
chrome.debugger.detach({ tabId }, resolve);
|
|
chrome.debugger.onEvent.removeListener(handleRequestIntercept);
|
|
});
|
|
}
|
|
|
|
const getType = (requestType: string) => {
|
|
switch (requestType) {
|
|
case "Fetch":
|
|
case "XHR":
|
|
case "xmlhttprequest":
|
|
return 'xmlhttprequest'
|
|
default:
|
|
return requestType
|
|
}
|
|
}
|
|
function handleRequestIntercept(source, method, params) {
|
|
if (!source.tabId) return; // Not our target tab
|
|
if (!params.request) return; // No request object
|
|
if (params.request.method === "OPTIONS") return; // Ignore preflight requests
|
|
|
|
switch (method) {
|
|
case "Network.requestWillBeSent":
|
|
const reqType = params.type ? getType(params.type) : "resource";
|
|
if (reqType !== "xmlhttprequest") {
|
|
console.log(params);
|
|
}
|
|
|
|
requestMap[params.requestId] = {
|
|
encodedBodySize: 0,
|
|
responseBodySize: 0,
|
|
duration: 0,
|
|
method: params.request.method,
|
|
type: reqType,
|
|
statusCode: 0,
|
|
url: params.request.url,
|
|
body: params.request.postData || "",
|
|
responseBody: "",
|
|
fromCache: false,
|
|
requestHeaders: params.request.headers || {},
|
|
responseHeaders: {},
|
|
timestamp: Date.now(),
|
|
};
|
|
break;
|
|
|
|
case "Network.responseReceived":
|
|
if (!requestMap[params.requestId]) return;
|
|
requestMap[params.requestId].statusCode = params.response.status;
|
|
requestMap[params.requestId].responseHeaders =
|
|
params.response.headers || {};
|
|
// fromDiskCache or fromServiceWorker if available
|
|
if (params.response.fromDiskCache)
|
|
requestMap[params.requestId].fromCache = true;
|
|
break;
|
|
|
|
case "Network.dataReceived":
|
|
if (!requestMap[params.requestId]) return;
|
|
requestMap[params.requestId].encodedBodySize += params.dataLength;
|
|
// There's no direct content-encoding size from debugger
|
|
break;
|
|
|
|
case "Network.loadingFinished":
|
|
if (!requestMap[params.requestId]) return;
|
|
requestMap[params.requestId].duration =
|
|
Date.now() - requestMap[params.requestId].time;
|
|
requestMap[params.requestId].responseBodySize =
|
|
requestMap[params.requestId].encodedBodySize;
|
|
chrome.debugger.sendCommand(
|
|
{ tabId: source.tabId },
|
|
"Network.getResponseBody",
|
|
{ requestId: params.requestId },
|
|
(res) => {
|
|
if (!res || res.error) {
|
|
requestMap[params.requestId].error = res?.error || "Unknown";
|
|
} else {
|
|
requestMap[params.requestId].responseBody = res.base64Encoded
|
|
? atob(res.body)
|
|
: res.body;
|
|
}
|
|
},
|
|
);
|
|
break;
|
|
|
|
case "Network.loadingFailed":
|
|
if (!requestMap[params.requestId]) return;
|
|
requestMap[params.requestId].error = params.errorText || "Unknown";
|
|
break;
|
|
}
|
|
}
|
|
|
|
export const getRequests = () => {
|
|
return Object.values(requestMap);
|
|
};
|