diff --git a/src/browser/tests/net/xhr.html b/src/browser/tests/net/xhr.html index b7132f6e..61cfb1ee 100644 --- a/src/browser/tests/net/xhr.html +++ b/src/browser/tests/net/xhr.html @@ -222,3 +222,34 @@ testing.expectEqual(XMLHttpRequest.UNSENT, req.readyState); }); + + + --> diff --git a/src/http/Client.zig b/src/http/Client.zig index 3cce2ddb..4072b548 100644 --- a/src/http/Client.zig +++ b/src/http/Client.zig @@ -1092,6 +1092,8 @@ pub const Transfer = struct { // the headers, and the [encoded] body. bytes_received: usize = 0, + aborted: bool = false, + max_response_size: ?usize = null, // We'll store the response header here @@ -1224,10 +1226,18 @@ pub const Transfer = struct { pub fn abort(self: *Transfer, err: anyerror) void { requestFailed(self, err, true); - if (self._handle != null) { - self.client.endTransfer(self); + if (self._handle == null) { + self.deinit(); + return; } - self.deinit(); + + // abort can be called from a libcurl callback, e.g. we get data, we + // do the header done callback, the client aborts. + // libcurl doesn't support re-entrant calls. We can't remove the + // handle from the multi during a callback. Instead, we flag this as + // aborted, which will signal the callbacks to stop processing the + // transfer + self.aborted = true; } pub fn terminate(self: *Transfer) void { @@ -1359,7 +1369,7 @@ pub const Transfer = struct { .transfer = transfer, }); - return proceed; + return proceed and transfer.aborted == false; } // headerCallback is called by curl on each request's header line read. @@ -1519,6 +1529,10 @@ pub const Transfer = struct { .transfer = transfer, }); + if (transfer.aborted) { + return -1; + } + return @intCast(chunk_len); }