Merge pull request #1694 from lightpanda-io/client_abort_frame
Some checks failed
e2e-test / zig build release (push) Has been cancelled
e2e-test / demo-scripts (push) Has been cancelled
e2e-test / cdp-and-hyperfine-bench (push) Has been cancelled
e2e-test / perf-fmt (push) Has been cancelled
e2e-test / browser fetch (push) Has been cancelled
zig-test / zig test using v8 in debug mode (push) Has been cancelled
zig-test / zig test (push) Has been cancelled
zig-test / perf-fmt (push) Has been cancelled
nightly build / build-linux-x86_64 (push) Has been cancelled
nightly build / build-linux-aarch64 (push) Has been cancelled
nightly build / build-macos-aarch64 (push) Has been cancelled
nightly build / build-macos-x86_64 (push) Has been cancelled
wpt / zig build release (push) Has been cancelled
wpt / build wpt runner (push) Has been cancelled
wpt / web platform tests json output (push) Has been cancelled
wpt / perf-fmt (push) Has been cancelled
e2e-integration-test / zig build release (push) Has been cancelled
e2e-integration-test / demo-integration-scripts (push) Has been cancelled

Allow frame-specific HTTP abort
This commit is contained in:
Karl Seguin
2026-03-02 18:11:33 +08:00
committed by GitHub

View File

@@ -174,27 +174,59 @@ pub fn newHeaders(self: *const Client) !Net.Headers {
} }
pub fn abort(self: *Client) void { pub fn abort(self: *Client) void {
while (self.handles.in_use.first) |node| { self._abort(true, 0);
}
pub fn abortFrame(self: *Client, frame_id: u32) void {
self._abort(false, frame_id);
}
// Written this way so that both abort and abortFrame can share the same code
// but abort can avoid the frame_id check at comptime.
fn _abort(self: *Client, comptime abort_all: bool, frame_id: u32) void {
{
var q = &self.handles.in_use;
var n = q.first;
while (n) |node| {
n = node.next;
const conn: *Net.Connection = @fieldParentPtr("node", node); const conn: *Net.Connection = @fieldParentPtr("node", node);
var transfer = Transfer.fromConnection(conn) catch |err| { var transfer = Transfer.fromConnection(conn) catch |err| {
log.err(.http, "get private info", .{ .err = err, .source = "abort" }); log.err(.http, "get private info", .{ .err = err, .source = "abort" });
continue; continue;
}; };
if (comptime abort_all) {
transfer.kill();
} else if (transfer.req.frame_id == frame_id) {
q.remove(node);
transfer.kill(); transfer.kill();
} }
if (comptime IS_DEBUG) { }
}
if (comptime IS_DEBUG and abort_all) {
std.debug.assert(self.active == 0); std.debug.assert(self.active == 0);
} }
var n = self.queue.first; {
var q = &self.queue;
var n = q.first;
while (n) |node| { while (n) |node| {
n = node.next; n = node.next;
const transfer: *Transfer = @fieldParentPtr("_node", node); const transfer: *Transfer = @fieldParentPtr("_node", node);
if (comptime abort_all) {
transfer.kill();
} else if (transfer.req.frame_id == frame_id) {
q.remove(node);
transfer.kill(); transfer.kill();
} }
self.queue = .{}; }
}
if (comptime IS_DEBUG) { if (comptime abort_all) {
self.queue = .{};
}
if (comptime IS_DEBUG and abort_all) {
std.debug.assert(self.handles.in_use.first == null); std.debug.assert(self.handles.in_use.first == null);
std.debug.assert(self.handles.available.len() == self.handles.connections.len); std.debug.assert(self.handles.available.len() == self.handles.connections.len);