From 6d41ea6fd047ac2217534ac8cb6abdc6b5163a87 Mon Sep 17 00:00:00 2001 From: Muki Kiboigo Date: Sun, 26 Apr 2026 18:10:13 -0700 Subject: [PATCH] move arena up to Request instead of Transfer --- src/browser/HttpClient.zig | 27 +++++++++++---------------- src/cdp/domains/fetch.zig | 6 +++--- src/cdp/domains/network.zig | 15 +++++++-------- src/network/layer/RobotsLayer.zig | 2 ++ 4 files changed, 23 insertions(+), 27 deletions(-) diff --git a/src/browser/HttpClient.zig b/src/browser/HttpClient.zig index ef924e3f..6becf460 100644 --- a/src/browser/HttpClient.zig +++ b/src/browser/HttpClient.zig @@ -401,7 +401,6 @@ pub fn tick(self: *Client, timeout_ms: u32) !PerformStatus { pub fn _request(ptr: *anyopaque, _: *Client, req: Request) !void { const self: *Client = @ptrCast(@alignCast(ptr)); - const transfer = try self.makeTransfer(req); var wait_for_interception = false; @@ -436,6 +435,8 @@ pub fn request(self: *Client, req: Request) !void { // Assign Request Id. var our_req = req; our_req.params.request_id = self.incrReqId(); + our_req.params.arena = ArenaAllocator.init(self.allocator); + return self.entry_layer.request(self, our_req); } @@ -621,14 +622,11 @@ pub fn incrReqId(self: *Client) u32 { } fn makeTransfer(self: *Client, req: Request) !*Transfer { - errdefer req.params.headers.deinit(); - const transfer = try self.transfer_pool.create(); errdefer self.transfer_pool.destroy(transfer); transfer.* = .{ .start_time = timestamp(.monotonic), - .arena = ArenaAllocator.init(self.allocator), .id = req.params.request_id, .url = req.params.url, .req = req, @@ -1007,6 +1005,8 @@ fn ensureNoActiveConnection(self: *const Client) !void { } pub const RequestParams = struct { + /// This is unsafe to access until you pass it to `Client.request()` where it gets assigned. + arena: ArenaAllocator = undefined, /// This is unsafe to access until you pass it to `Client.request()` where it gets assigned. request_id: u32 = undefined, frame_id: u32, @@ -1051,6 +1051,7 @@ pub const RequestParams = struct { pub fn deinit(self: *const RequestParams) void { self.headers.deinit(); + self.arena.deinit(); } }; @@ -1073,9 +1074,9 @@ pub const Request = struct { error_callback: ErrorCallback, shutdown_callback: ?ShutdownCallback = null, - pub fn getCookieString(self: *Request, allocator: std.mem.Allocator) !?[:0]const u8 { + pub fn getCookieString(self: *Request) !?[:0]const u8 { const jar = self.params.cookie_jar orelse return null; - var aw: std.Io.Writer.Allocating = .init(allocator); + var aw: std.Io.Writer.Allocating = .init(self.params.arena.allocator()); try jar.forRequest(self.params.url, &aw.writer, .{ .is_http = true, .origin_url = self.params.cookie_origin, @@ -1177,7 +1178,6 @@ pub const SyncResponse = struct { }; pub const Transfer = struct { - arena: ArenaAllocator, id: u32 = 0, req: Request, url: [:0]const u8, @@ -1245,7 +1245,6 @@ pub const Transfer = struct { } self.req.deinit(); - self.arena.deinit(); self.client.transfer_pool.destroy(self); } @@ -1337,7 +1336,7 @@ pub const Transfer = struct { try conn.setHeaders(&header_list); // Add cookies from cookie jar. - if (try self.getCookieString()) |cookies| { + if (try self.req.getCookieString()) |cookies| { try conn.setCookies(@ptrCast(cookies.ptr)); } @@ -1398,10 +1397,6 @@ pub const Transfer = struct { } } - pub fn getCookieString(self: *Transfer) !?[:0]const u8 { - return self.req.getCookieString(self.arena.allocator()); - } - pub fn format(self: *Transfer, writer: *std.Io.Writer) !void { const req = self.req; return writer.print("{s} {s}", .{ @tagName(req.params.method), req.params.url }); @@ -1418,7 +1413,7 @@ pub const Transfer = struct { fn handleRedirect(transfer: *Transfer) !void { const req = &transfer.req; const conn = transfer._conn.?; - const arena = transfer.arena.allocator(); + const arena = transfer.req.params.arena.allocator(); transfer._redirect_count += 1; if (transfer._redirect_count > transfer.client.network.config.httpMaxRedirects()) { @@ -1602,7 +1597,7 @@ pub const Transfer = struct { transfer._callback_error = error.ResponseTooLarge; return http.writefunc_error; } - transfer._stream_buffer.ensureTotalCapacity(transfer.arena.allocator(), cl) catch {}; + transfer._stream_buffer.ensureTotalCapacity(transfer.req.params.arena.allocator(), cl) catch {}; } } @@ -1615,7 +1610,7 @@ pub const Transfer = struct { } const chunk = buffer[0..chunk_len]; - transfer._stream_buffer.appendSlice(transfer.arena.allocator(), chunk) catch |err| { + transfer._stream_buffer.appendSlice(transfer.req.params.arena.allocator(), chunk) catch |err| { transfer._callback_error = err; return http.writefunc_error; }; diff --git a/src/cdp/domains/fetch.zig b/src/cdp/domains/fetch.zig index 57d0bd56..452c4d05 100644 --- a/src/cdp/domains/fetch.zig +++ b/src/cdp/domains/fetch.zig @@ -245,7 +245,7 @@ fn continueRequest(cmd: *CDP.Command) !void { .new_url = params.url, }); - const arena = transfer.arena.allocator(); + const arena = transfer.req.params.arena.allocator(); // Update the request with the new parameters if (params.url) |url| { try transfer.updateURL(try arena.dupeZ(u8, url)); @@ -309,7 +309,7 @@ fn continueWithAuth(cmd: *CDP.Command) !void { errdefer transfer.abortAuthChallenge(); // restart the request with the provided credentials. - const arena = transfer.arena.allocator(); + const arena = transfer.req.params.arena.allocator(); transfer.updateCredentials( try std.fmt.allocPrintSentinel(arena, "{s}:{s}", .{ params.authChallengeResponse.username, @@ -354,7 +354,7 @@ fn fulfillRequest(cmd: *CDP.Command) !void { var body: ?[]const u8 = null; if (params.body) |b| { const decoder = std.base64.standard.Decoder; - const buf = try transfer.arena.allocator().alloc(u8, try decoder.calcSizeForSlice(b)); + const buf = try transfer.req.params.arena.allocator().alloc(u8, try decoder.calcSizeForSlice(b)); try decoder.decode(buf, b); body = buf; } diff --git a/src/cdp/domains/network.zig b/src/cdp/domains/network.zig index f9e17194..4f34dd36 100644 --- a/src/cdp/domains/network.zig +++ b/src/cdp/domains/network.zig @@ -329,9 +329,9 @@ pub fn httpRequestDone(bc: *CDP.BrowserContext, msg: *const Notification.Request } pub const RequestWriter = struct { - request: *const Request, + request: *Request, - pub fn init(request: *const Request) RequestWriter { + pub fn init(request: *Request) RequestWriter { return .{ .request = request, }; @@ -376,11 +376,10 @@ pub const RequestWriter = struct { try jws.objectField(hdr.name); try jws.write(hdr.value); } - // TODO: Fix. - // if (try request.getCookieString()) |cookies| { - // try jws.objectField("Cookie"); - // try jws.write(cookies[0 .. cookies.len - 1]); - // } + if (try request.getCookieString()) |cookies| { + try jws.objectField("Cookie"); + try jws.write(cookies[0 .. cookies.len - 1]); + } try jws.endObject(); } try jws.endObject(); @@ -434,7 +433,7 @@ pub const TransferAsRequestWriter = struct { try jws.objectField(hdr.name); try jws.write(hdr.value); } - if (try transfer.getCookieString()) |cookies| { + if (try transfer.req.getCookieString()) |cookies| { try jws.objectField("Cookie"); try jws.write(cookies[0 .. cookies.len - 1]); } diff --git a/src/network/layer/RobotsLayer.zig b/src/network/layer/RobotsLayer.zig index add4ee3d..e1de10a0 100644 --- a/src/network/layer/RobotsLayer.zig +++ b/src/network/layer/RobotsLayer.zig @@ -66,6 +66,8 @@ fn request(ptr: *anyopaque, client: *Client, req: Request) anyerror!void { const path = URL.getPathname(req.params.url); if (!robots.isAllowed(path)) { + defer req.deinit(); + log.warn(.http, "blocked by robots", .{ .url = req.params.url }); req.error_callback(req.ctx, error.RobotsBlocked); return;