Skip to content

Commit 8616aa8

Browse files
committed
swap onBeforeRequest for onSendHeaders observer
1 parent 322287f commit 8616aa8

2 files changed

Lines changed: 39 additions & 46 deletions

File tree

apps/code/src/main/utils/network-webrequest-logger.test.ts

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import type { ObservableWebRequest } from "./network-webrequest-logger";
2121
import { contentLengthFromHeaders } from "./network-webrequest-logger";
2222

2323
type Listeners = {
24-
onBeforeRequest: Parameters<ObservableWebRequest["onBeforeRequest"]>[1];
24+
onSendHeaders: Parameters<ObservableWebRequest["onSendHeaders"]>[1];
2525
onCompleted: Parameters<ObservableWebRequest["onCompleted"]>[1];
2626
onErrorOccurred: Parameters<ObservableWebRequest["onErrorOccurred"]>[1];
2727
};
@@ -33,8 +33,8 @@ function fakeWebRequest(): { webRequest: ObservableWebRequest } & {
3333
return {
3434
listeners,
3535
webRequest: {
36-
onBeforeRequest: (_filter, listener) => {
37-
listeners.onBeforeRequest = listener;
36+
onSendHeaders: (_filter, listener) => {
37+
listeners.onSendHeaders = listener;
3838
},
3939
onCompleted: (_filter, listener) => {
4040
listeners.onCompleted = listener;
@@ -84,29 +84,20 @@ describe("contentLengthFromHeaders", () => {
8484
});
8585

8686
describe("installRendererNetworkLogging", () => {
87-
it("always invokes the onBeforeRequest callback", async () => {
88-
const { listeners } = await installFresh();
89-
const callback = vi.fn();
90-
91-
listeners.onBeforeRequest(
92-
{ id: 1, method: "GET", url: "https://example.com/" },
93-
callback,
94-
);
95-
96-
expect(callback).toHaveBeenCalledWith({});
97-
});
98-
9987
it("records a completed request and mirrors it to the dev toolbar", async () => {
10088
const { listeners, devNetwork, record } = await installFresh();
10189

102-
listeners.onBeforeRequest(
103-
{ id: 7, method: "GET", url: "https://us.posthog.com/api/" },
104-
vi.fn(),
105-
);
90+
listeners.onSendHeaders({
91+
id: 7,
92+
method: "GET",
93+
url: "https://us.posthog.com/api/",
94+
timestamp: 1_000,
95+
});
10696
listeners.onCompleted({
10797
id: 7,
10898
method: "GET",
10999
url: "https://us.posthog.com/api/",
100+
timestamp: 1_290,
110101
statusCode: 200,
111102
responseHeaders: { "Content-Length": ["1834"] },
112103
});
@@ -116,14 +107,16 @@ describe("installRendererNetworkLogging", () => {
116107
method: "GET",
117108
url: "https://us.posthog.com/api/",
118109
status: 200,
119-
durationMs: expect.any(Number),
110+
durationMs: 290,
120111
bytes: 1834,
121112
});
122113
expect(devNetwork.recordExternal).toHaveBeenCalledWith(
123114
expect.objectContaining({
124115
origin: "renderer",
125116
status: 200,
126117
ok: true,
118+
durationMs: 290,
119+
startedAt: 1_000,
127120
bytes: 1834,
128121
}),
129122
);
@@ -132,14 +125,17 @@ describe("installRendererNetworkLogging", () => {
132125
it("records a failed request with the chromium error string", async () => {
133126
const { listeners, devNetwork, record } = await installFresh();
134127

135-
listeners.onBeforeRequest(
136-
{ id: 9, method: "POST", url: "https://example.com/x" },
137-
vi.fn(),
138-
);
128+
listeners.onSendHeaders({
129+
id: 9,
130+
method: "POST",
131+
url: "https://example.com/x",
132+
timestamp: 5_000,
133+
});
139134
listeners.onErrorOccurred({
140135
id: 9,
141136
method: "POST",
142137
url: "https://example.com/x",
138+
timestamp: 5_120,
143139
error: "net::ERR_CONNECTION_RESET",
144140
});
145141

@@ -148,13 +144,15 @@ describe("installRendererNetworkLogging", () => {
148144
method: "POST",
149145
url: "https://example.com/x",
150146
status: null,
151-
durationMs: expect.any(Number),
147+
durationMs: 120,
152148
bytes: null,
153149
error: "net::ERR_CONNECTION_RESET",
154150
});
155151
expect(devNetwork.recordExternal).toHaveBeenCalledWith(
156152
expect.objectContaining({
157153
ok: false,
154+
durationMs: 120,
155+
startedAt: 5_000,
158156
error: "net::ERR_CONNECTION_RESET",
159157
}),
160158
);
@@ -167,6 +165,7 @@ describe("installRendererNetworkLogging", () => {
167165
id: 3,
168166
method: "GET",
169167
url: "https://example.com/missing",
168+
timestamp: 2_000,
170169
statusCode: 404,
171170
});
172171

@@ -175,13 +174,14 @@ describe("installRendererNetworkLogging", () => {
175174
);
176175
});
177176

178-
it("still records completions whose start entry was evicted", async () => {
177+
it("still records completions with no start entry (evicted or cache hit that skipped onSendHeaders)", async () => {
179178
const { listeners, record } = await installFresh();
180179

181180
listeners.onCompleted({
182181
id: 999,
183182
method: "GET",
184183
url: "https://example.com/",
184+
timestamp: 3_000,
185185
statusCode: 200,
186186
});
187187

apps/code/src/main/utils/network-webrequest-logger.ts

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ interface RequestDetails {
99
id: number;
1010
method: string;
1111
url: string;
12+
timestamp: number;
1213
}
1314

1415
interface CompletedDetails extends RequestDetails {
@@ -21,12 +22,9 @@ interface FailedDetails extends RequestDetails {
2122
}
2223

2324
export interface ObservableWebRequest {
24-
onBeforeRequest(
25+
onSendHeaders(
2526
filter: WebRequestFilter,
26-
listener: (
27-
details: RequestDetails,
28-
callback: (response: { cancel?: boolean }) => void,
29-
) => void,
27+
listener: (details: RequestDetails) => void,
3028
): void;
3129
onCompleted(
3230
filter: WebRequestFilter,
@@ -45,18 +43,18 @@ interface PendingRequest {
4543
const MAX_PENDING_REQUESTS = 2000;
4644
const pending = new Map<number, PendingRequest>();
4745

48-
function trackPending(id: number): void {
46+
function trackPending(id: number, startedAt: number): void {
4947
if (pending.size >= MAX_PENDING_REQUESTS) {
5048
const oldest = pending.keys().next().value;
5149
if (oldest !== undefined) pending.delete(oldest);
5250
}
53-
pending.set(id, { startedAt: Date.now() });
51+
pending.set(id, { startedAt });
5452
}
5553

56-
function takeDuration(id: number): number {
54+
function takeDuration(id: number, endedAt: number): number {
5755
const start = pending.get(id);
5856
pending.delete(id);
59-
return start ? Date.now() - start.startedAt : 0;
57+
return start ? endedAt - start.startedAt : 0;
6058
}
6159

6260
export function contentLengthFromHeaders(
@@ -80,17 +78,12 @@ export function installRendererNetworkLogging(
8078

8179
const filter: WebRequestFilter = { urls: ["http://*/*", "https://*/*"] };
8280

83-
webRequest.onBeforeRequest(filter, (details, callback) => {
84-
// Chromium stalls the request forever if the callback never runs.
85-
try {
86-
trackPending(details.id);
87-
} finally {
88-
callback({});
89-
}
81+
webRequest.onSendHeaders(filter, (details) => {
82+
trackPending(details.id, details.timestamp);
9083
});
9184

9285
webRequest.onCompleted(filter, (details) => {
93-
const durationMs = takeDuration(details.id);
86+
const durationMs = takeDuration(details.id, details.timestamp);
9487
const bytes = contentLengthFromHeaders(details.responseHeaders);
9588
recordNetworkRequest({
9689
origin: "renderer",
@@ -107,13 +100,13 @@ export function installRendererNetworkLogging(
107100
status: details.statusCode,
108101
ok: details.statusCode >= 200 && details.statusCode < 300,
109102
durationMs,
110-
startedAt: Date.now() - durationMs,
103+
startedAt: details.timestamp - durationMs,
111104
bytes,
112105
});
113106
});
114107

115108
webRequest.onErrorOccurred(filter, (details) => {
116-
const durationMs = takeDuration(details.id);
109+
const durationMs = takeDuration(details.id, details.timestamp);
117110
recordNetworkRequest({
118111
origin: "renderer",
119112
method: details.method,
@@ -130,7 +123,7 @@ export function installRendererNetworkLogging(
130123
status: null,
131124
ok: false,
132125
durationMs,
133-
startedAt: Date.now() - durationMs,
126+
startedAt: details.timestamp - durationMs,
134127
bytes: null,
135128
error: details.error,
136129
});

0 commit comments

Comments
 (0)