encode captured response depending of the content type

This commit is contained in:
Pierre Tachoire
2026-03-21 14:08:08 +01:00
parent 00d06dbe8c
commit 30f387d361
2 changed files with 42 additions and 10 deletions

View File

@@ -386,6 +386,14 @@ pub fn isHTML(self: *const Mime) bool {
return self.content_type == .text_html; return self.content_type == .text_html;
} }
pub fn isText(mime: *const Mime) bool {
return switch (mime.content_type) {
.text_xml, .text_html, .text_javascript, .text_plain, .text_css => true,
.application_json => true,
else => false,
};
}
// we expect value to be lowercase // we expect value to be lowercase
fn parseContentType(value: []const u8) !struct { ContentType, usize } { fn parseContentType(value: []const u8) !struct { ContentType, usize } {
const end = std.mem.indexOfScalarPos(u8, value, 0, ';') orelse value.len; const end = std.mem.indexOfScalarPos(u8, value, 0, ';') orelse value.len;

View File

@@ -33,6 +33,7 @@ const Page = @import("../browser/Page.zig");
const Incrementing = @import("id.zig").Incrementing; const Incrementing = @import("id.zig").Incrementing;
const Notification = @import("../Notification.zig"); const Notification = @import("../Notification.zig");
const InterceptState = @import("domains/fetch.zig").InterceptState; const InterceptState = @import("domains/fetch.zig").InterceptState;
const Mime = @import("../browser/Mime.zig");
pub const URL_BASE = "chrome://newtab/"; pub const URL_BASE = "chrome://newtab/";
@@ -638,6 +639,35 @@ pub fn BrowserContext(comptime CDP_T: type) type {
pub fn onHttpResponseHeadersDone(ctx: *anyopaque, msg: *const Notification.ResponseHeaderDone) !void { pub fn onHttpResponseHeadersDone(ctx: *anyopaque, msg: *const Notification.ResponseHeaderDone) !void {
const self: *Self = @ptrCast(@alignCast(ctx)); const self: *Self = @ptrCast(@alignCast(ctx));
defer self.resetNotificationArena(); defer self.resetNotificationArena();
const arena = self.page_arena;
// Prepare the captured response value.
const id = msg.transfer.id;
const gop = try self.captured_responses.getOrPut(arena, id);
if (!gop.found_existing) {
gop.value_ptr.* = .{
.data = .empty,
// Encode the data in base64 by default, but use none
// encoding for well known content-type.
.encode = blk: {
const transfer = msg.transfer;
if (transfer.response_header.?.contentType()) |ct| {
const mime = try Mime.parse(ct);
if (!mime.isText()) {
break :blk .base64;
}
if (std.mem.eql(u8, "UTF-8", mime.charsetString())) {
break :blk .none;
}
}
break :blk .base64;
},
};
}
return @import("domains/network.zig").httpResponseHeaderDone(self.notification_arena, self, msg); return @import("domains/network.zig").httpResponseHeaderDone(self.notification_arena, self, msg);
} }
@@ -651,18 +681,12 @@ pub fn BrowserContext(comptime CDP_T: type) type {
const arena = self.page_arena; const arena = self.page_arena;
const id = msg.transfer.id; const id = msg.transfer.id;
const gop = try self.captured_responses.getOrPut(arena, id); const resp = self.captured_responses.getPtr(id) orelse lp.assert(false, "onHttpResponseData missinf captured response", .{});
if (!gop.found_existing) {
gop.value_ptr.* = .{ if (resp.encode == .none) {
.data = .empty, return resp.data.appendSlice(arena, msg.data);
.encode = .base64,
};
} }
// Always base64 ecncode the catured response body.
// TODO: use the response's content-type to decide to encode or not
// the body.
const resp = gop.value_ptr;
const encoded_len = std.base64.standard.Encoder.calcSize(msg.data.len); const encoded_len = std.base64.standard.Encoder.calcSize(msg.data.len);
const start = resp.data.items.len; const start = resp.data.items.len;
try resp.data.resize(arena, start + encoded_len); try resp.data.resize(arena, start + encoded_len);