Skip to content

Commit 6b001c5

Browse files
committed
Emits a http_request_done internal notification.
With networking enabled, CDP listens to this event and emits a `Network.loadingFinished` event. This is event is used by puppeteer to know that details about the response (i.e. the body) can be queries. Added dummy handling for the Network.getResponseBody message. Returns an empty body. Needed because we emit the loadingFinished event which signals to drivers that they can ask for the body.
1 parent bade412 commit 6b001c5

File tree

4 files changed

+60
-2
lines changed

4 files changed

+60
-2
lines changed

src/cdp/cdp.zig

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,12 +455,14 @@ pub fn BrowserContext(comptime CDP_T: type) type {
455455
try self.cdp.browser.notification.register(.http_request_fail, self, onHttpRequestFail);
456456
try self.cdp.browser.notification.register(.http_request_start, self, onHttpRequestStart);
457457
try self.cdp.browser.notification.register(.http_headers_done, self, onHttpHeadersDone);
458+
try self.cdp.browser.notification.register(.http_request_done, self, onHttpRequestDone);
458459
}
459460

460461
pub fn networkDisable(self: *Self) void {
461462
self.cdp.browser.notification.unregister(.http_request_fail, self);
462463
self.cdp.browser.notification.unregister(.http_request_start, self);
463464
self.cdp.browser.notification.unregister(.http_headers_done, self);
465+
self.cdp.browser.notification.unregister(.http_request_done, self);
464466
}
465467

466468
pub fn fetchEnable(self: *Self) !void {
@@ -516,6 +518,12 @@ pub fn BrowserContext(comptime CDP_T: type) type {
516518
return @import("domains/network.zig").httpHeadersDone(self.notification_arena, self, data);
517519
}
518520

521+
pub fn onHttpRequestDone(ctx: *anyopaque, data: *const Notification.RequestDone) !void {
522+
const self: *Self = @alignCast(@ptrCast(ctx));
523+
defer self.resetNotificationArena();
524+
return @import("domains/network.zig").httpRequestDone(self.notification_arena, self, data);
525+
}
526+
519527
fn resetNotificationArena(self: *Self) void {
520528
defer _ = self.cdp.notification_arena.reset(.{ .retain_with_limit = 1024 * 64 });
521529
}

src/cdp/domains/network.zig

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ pub fn processMessage(cmd: anytype) !void {
3636
setCookie,
3737
setCookies,
3838
getCookies,
39+
getResponseBody,
3940
}, cmd.input.action) orelse return error.UnknownMethod;
4041

4142
switch (action) {
@@ -49,6 +50,7 @@ pub fn processMessage(cmd: anytype) !void {
4950
.setCookie => return setCookie(cmd),
5051
.setCookies => return setCookies(cmd),
5152
.getCookies => return getCookies(cmd),
53+
.getResponseBody => return getResponseBody(cmd),
5254
}
5355
}
5456

@@ -202,6 +204,19 @@ fn getCookies(cmd: anytype) !void {
202204
try cmd.sendResult(.{ .cookies = writer }, .{});
203205
}
204206

207+
fn getResponseBody(cmd: anytype) !void {
208+
const params = (try cmd.params(struct {
209+
requestId: []const u8, // "REQ-{d}"
210+
})) orelse return error.InvalidParams;
211+
212+
_ = params;
213+
214+
try cmd.sendResult(.{
215+
.body = "TODO",
216+
.base64Encoded = false,
217+
}, .{});
218+
}
219+
205220
pub fn httpRequestFail(arena: Allocator, bc: anytype, data: *const Notification.RequestFail) !void {
206221
// It's possible that the request failed because we aborted when the client
207222
// sent Target.closeTarget. In that case, bc.session_id will be cleared
@@ -264,6 +279,22 @@ pub fn httpHeadersDone(arena: Allocator, bc: anytype, data: *const Notification.
264279
}, .{ .session_id = session_id });
265280
}
266281

282+
pub fn httpRequestDone(arena: Allocator, bc: anytype, data: *const Notification.RequestDone) !void {
283+
// Isn't possible to do a network request within a Browser (which our
284+
// notification is tied to), without a page.
285+
std.debug.assert(bc.session.page != null);
286+
287+
var cdp = bc.cdp;
288+
289+
// all unreachable because we _have_ to have a page.
290+
const session_id = bc.session_id orelse unreachable;
291+
292+
try cdp.sendEvent("Network.loadingFinished", .{
293+
.requestId = try std.fmt.allocPrint(arena, "REQ-{d}", .{data.transfer.id}),
294+
.encodedDataLength = data.transfer.bytes_received,
295+
}, .{ .session_id = session_id });
296+
}
297+
267298
pub const TransferAsRequestWriter = struct {
268299
transfer: *Transfer,
269300

src/http/Client.zig

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -376,8 +376,14 @@ fn perform(self: *Client, timeout_ms: c_int) !void {
376376
// transfer isn't valid at this point, don't use it.
377377
log.err(.http, "done_callback", .{ .err = err });
378378
self.requestFailed(transfer, err);
379+
continue;
379380
};
380-
// self.requestComplete(transfer);
381+
382+
if (transfer.client.notification) |notification| {
383+
notification.dispatch(.http_request_done, &.{
384+
.transfer = transfer,
385+
});
386+
}
381387
} else |err| {
382388
self.requestFailed(transfer, err);
383389
}
@@ -552,11 +558,15 @@ pub const Transfer = struct {
552558
uri: std.Uri, // used for setting/getting the cookie
553559
ctx: *anyopaque, // copied from req.ctx to make it easier for callback handlers
554560
client: *Client,
555-
_notified_fail: bool = false,
561+
// total bytes received in the response, including the response status line,
562+
// the headers, and the [encoded] body.
563+
bytes_received: usize = 0,
556564

557565
// We'll store the response header here
558566
response_header: ?ResponseHeader = null,
559567

568+
_notified_fail: bool = false,
569+
560570
_handle: ?*Handle = null,
561571

562572
_redirecting: bool = false,
@@ -716,9 +726,11 @@ pub const Transfer = struct {
716726
.url = url,
717727
.status = status,
718728
};
729+
transfer.bytes_received = buf_len;
719730
return buf_len;
720731
}
721732

733+
transfer.bytes_received += buf_len;
722734
if (buf_len == 2) {
723735
if (getResponseHeader(easy, "content-type", 0)) |ct| {
724736
var hdr = &transfer.response_header.?;
@@ -777,6 +789,7 @@ pub const Transfer = struct {
777789
return chunk_len;
778790
}
779791

792+
transfer.bytes_received += chunk_len;
780793
transfer.req.data_callback(transfer, buffer[0..chunk_len]) catch |err| {
781794
log.err(.http, "data_callback", .{ .err = err, .req = transfer });
782795
return c.CURL_WRITEFUNC_ERROR;

src/notification.zig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ pub const Notification = struct {
6464
http_request_start: List = .{},
6565
http_request_intercept: List = .{},
6666
http_headers_done: List = .{},
67+
http_request_done: List = .{},
6768
notification_created: List = .{},
6869
};
6970

@@ -76,6 +77,7 @@ pub const Notification = struct {
7677
http_request_start: *const RequestStart,
7778
http_request_intercept: *const RequestIntercept,
7879
http_headers_done: *const ResponseHeadersDone,
80+
http_request_done: *const RequestDone,
7981
notification_created: *Notification,
8082
};
8183
const EventType = std.meta.FieldEnum(Events);
@@ -106,6 +108,10 @@ pub const Notification = struct {
106108
transfer: *Transfer,
107109
};
108110

111+
pub const RequestDone = struct {
112+
transfer: *Transfer,
113+
};
114+
109115
pub const RequestFail = struct {
110116
transfer: *Transfer,
111117
err: anyerror,

0 commit comments

Comments
 (0)