Skip to content

Commit 2a8e51c

Browse files
committed
Pre-size the destination buffer when we know the response content length
1 parent f66f4d9 commit 2a8e51c

File tree

3 files changed

+25
-1
lines changed

3 files changed

+25
-1
lines changed

src/browser/ScriptManager.zig

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,14 @@ 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+
if (cl > 100 * 1024 * 1024) {
486+
return error.ResponseTooLarge;
487+
}
488+
try buffer.ensureTotalCapacity(self.manager.allocator, cl);
489+
}
490+
self.script.source = .{ .remote = buffer };
484491
}
485492

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

src/browser/xhr/xhr.zig

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

439439
self.state = .loading;
440440
self.dispatchEvt("readystatechange");
441+
442+
if (transfer.getContentLength()) |cl| {
443+
if (cl > 100 * 1024 * 1024) {
444+
return error.ResponseTooLarge;
445+
}
446+
try self.response_bytes.ensureTotalCapacity(self.arena, cl);
447+
}
441448
}
442449

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

src/http/Client.zig

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

10411041
try req.done_callback(req.ctx);
10421042
}
1043+
1044+
pub fn getContentLength(self: *const Transfer) ?u32 {
1045+
// It's possible for this to be null even with correct code, due to
1046+
// request fulfillment. If transfer.fulfill is called, we won't have
1047+
// a handle.
1048+
const handle = self._handle orelse return null;
1049+
1050+
const cl = getResponseHeader(handle.conn.easy, "content-length", 0) orelse return null;
1051+
return std.fmt.parseInt(u32, cl.value, 10) catch null;
1052+
}
10431053
};
10441054

10451055
pub const ResponseHeader = struct {

0 commit comments

Comments
 (0)