Skip to content

Commit 87d48b0

Browse files
authored
Merge pull request #992 from lightpanda-io/http_buffer_presize
Pre-size the destination buffer when we know the response content length
2 parents ce08cc9 + 785a8da commit 87d48b0

File tree

3 files changed

+38
-1
lines changed

3 files changed

+38
-1
lines changed

src/browser/ScriptManager.zig

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,11 @@ const PendingScript = struct {
480480
// will fail. This assertion exists to catch incorrect assumptions about
481481
// how libcurl works, or about how we've configured it.
482482
std.debug.assert(self.script.source.remote.capacity == 0);
483-
self.script.source = .{ .remote = self.manager.buffer_pool.get() };
483+
var buffer = self.manager.buffer_pool.get();
484+
if (transfer.getContentLength()) |cl| {
485+
try buffer.ensureTotalCapacity(self.manager.allocator, cl);
486+
}
487+
self.script.source = .{ .remote = buffer };
484488
}
485489

486490
fn dataCallback(self: *PendingScript, transfer: *Http.Transfer, data: []const u8) !void {

src/browser/xhr/xhr.zig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,10 @@ pub const XMLHttpRequest = struct {
438438

439439
self.state = .loading;
440440
self.dispatchEvt("readystatechange");
441+
442+
if (transfer.getContentLength()) |cl| {
443+
try self.response_bytes.ensureTotalCapacity(self.arena, cl);
444+
}
441445
}
442446

443447
fn httpDataCallback(transfer: *Http.Transfer, data: []const u8) !void {

src/http/Client.zig

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,6 +1040,35 @@ pub const Transfer = struct {
10401040

10411041
try req.done_callback(req.ctx);
10421042
}
1043+
1044+
// This function should be called during the dataCallback. Calling it after
1045+
// such as in the doneCallback is guaranteed to return null.
1046+
pub fn getContentLength(self: *const Transfer) ?u32 {
1047+
const cl = self.getContentLengthRawValue() orelse return null;
1048+
return std.fmt.parseInt(u32, cl, 10) catch null;
1049+
}
1050+
1051+
fn getContentLengthRawValue(self: *const Transfer) ?[]const u8 {
1052+
if (self._handle) |handle| {
1053+
// If we have a handle, than this is a normal request. We can get the
1054+
// header value from the easy handle.
1055+
const cl = getResponseHeader(handle.conn.easy, "content-length", 0) orelse return null;
1056+
return cl.value;
1057+
}
1058+
1059+
// If we have no handle, then maybe this is being called after the
1060+
// doneCallback. OR, maybe this is a "fulfilled" request. Let's check
1061+
// the injected headers (if we have any).
1062+
1063+
const rh = self.response_header orelse return null;
1064+
for (rh._injected_headers) |hdr| {
1065+
if (std.ascii.eqlIgnoreCase(hdr.name, "content-length")) {
1066+
return hdr.value;
1067+
}
1068+
}
1069+
1070+
return null;
1071+
}
10431072
};
10441073

10451074
pub const ResponseHeader = struct {

0 commit comments

Comments
 (0)