mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-10-29 15:13:28 +00:00
Merge pull request #765 from lightpanda-io/http_client_optimization
Optimize the lifecycle of async requests
This commit is contained in:
@@ -468,7 +468,6 @@ pub const XMLHttpRequest = struct {
|
|||||||
|
|
||||||
if (progress.first) {
|
if (progress.first) {
|
||||||
const header = progress.header;
|
const header = progress.header;
|
||||||
|
|
||||||
log.debug(.http, "request header", .{
|
log.debug(.http, "request header", .{
|
||||||
.source = "xhr",
|
.source = "xhr",
|
||||||
.url = self.url,
|
.url = self.url,
|
||||||
@@ -522,7 +521,7 @@ pub const XMLHttpRequest = struct {
|
|||||||
log.info(.http, "request complete", .{
|
log.info(.http, "request complete", .{
|
||||||
.source = "xhr",
|
.source = "xhr",
|
||||||
.url = self.url,
|
.url = self.url,
|
||||||
.status = progress.header.status,
|
.status = self.response_status,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Not that the request is done, the http/client will free the request
|
// Not that the request is done, the http/client will free the request
|
||||||
|
|||||||
@@ -828,6 +828,7 @@ fn AsyncHandler(comptime H: type, comptime L: type) type {
|
|||||||
wait,
|
wait,
|
||||||
done,
|
done,
|
||||||
need_more,
|
need_more,
|
||||||
|
handler_error,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn deinit(self: *Self) void {
|
fn deinit(self: *Self) void {
|
||||||
@@ -966,12 +967,35 @@ fn AsyncHandler(comptime H: type, comptime L: type) type {
|
|||||||
switch (status) {
|
switch (status) {
|
||||||
.wait => {},
|
.wait => {},
|
||||||
.need_more => self.receive(),
|
.need_more => self.receive(),
|
||||||
|
.handler_error => {
|
||||||
|
// handler should never have been called if we're redirecting
|
||||||
|
std.debug.assert(self.redirect == null);
|
||||||
|
self.request.requestCompleted(self.reader.response);
|
||||||
|
self.deinit();
|
||||||
|
return;
|
||||||
|
},
|
||||||
.done => {
|
.done => {
|
||||||
const redirect = self.redirect orelse {
|
const redirect = self.redirect orelse {
|
||||||
|
var handler = self.handler;
|
||||||
self.request.requestCompleted(self.reader.response);
|
self.request.requestCompleted(self.reader.response);
|
||||||
self.deinit();
|
self.deinit();
|
||||||
|
|
||||||
|
// Emit the done chunk. We expect the caller to do
|
||||||
|
// processing once the full request is completed. By
|
||||||
|
// emiting this AFTER we've relreased the connection,
|
||||||
|
// we free the connection and its state for re-use.
|
||||||
|
// If we don't do this this way, we can end up with
|
||||||
|
// _a lot_ of pending request/states.
|
||||||
|
// DO NOT USE `self` here, it's no longer valid.
|
||||||
|
handler.onHttpResponse(.{
|
||||||
|
.data = null,
|
||||||
|
.done = true,
|
||||||
|
.first = false,
|
||||||
|
.header = .{},
|
||||||
|
}) catch {};
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
self.request.redirectAsync(redirect, self.loop, self.handler) catch |err| {
|
self.request.redirectAsync(redirect, self.loop, self.handler) catch |err| {
|
||||||
self.handleError("Setup async redirect", err);
|
self.handleError("Setup async redirect", err);
|
||||||
return;
|
return;
|
||||||
@@ -1116,22 +1140,22 @@ fn AsyncHandler(comptime H: type, comptime L: type) type {
|
|||||||
self.handler.onHttpResponse(.{
|
self.handler.onHttpResponse(.{
|
||||||
.data = chunk,
|
.data = chunk,
|
||||||
.first = first,
|
.first = first,
|
||||||
.done = next == null,
|
.done = false,
|
||||||
.header = reader.response,
|
.header = reader.response,
|
||||||
}) catch return .done;
|
}) catch return .handler_error;
|
||||||
|
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (result.data != null or done or would_be_first) {
|
} else if (result.data != null or would_be_first) {
|
||||||
// If we have data. Or if the request is done. Or if this is the
|
// If we have data. Or if the request is done. Or if this is the
|
||||||
// first time we have a complete header. Emit the chunk.
|
// first time we have a complete header. Emit the chunk.
|
||||||
self.handler.onHttpResponse(.{
|
self.handler.onHttpResponse(.{
|
||||||
.done = done,
|
.done = false,
|
||||||
.data = result.data,
|
.data = result.data,
|
||||||
.first = would_be_first,
|
.first = would_be_first,
|
||||||
.header = reader.response,
|
.header = reader.response,
|
||||||
}) catch return .done;
|
}) catch return .handler_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (done == true) {
|
if (done == true) {
|
||||||
@@ -3135,7 +3159,8 @@ const CaptureHandler = struct {
|
|||||||
const progress = try progress_;
|
const progress = try progress_;
|
||||||
const allocator = self.response.arena.allocator();
|
const allocator = self.response.arena.allocator();
|
||||||
try self.response.body.appendSlice(allocator, progress.data orelse "");
|
try self.response.body.appendSlice(allocator, progress.data orelse "");
|
||||||
if (progress.done) {
|
if (progress.first) {
|
||||||
|
std.debug.assert(!progress.done);
|
||||||
self.response.status = progress.header.status;
|
self.response.status = progress.header.status;
|
||||||
try self.response.headers.ensureTotalCapacity(allocator, progress.header.headers.items.len);
|
try self.response.headers.ensureTotalCapacity(allocator, progress.header.headers.items.len);
|
||||||
for (progress.header.headers.items) |header| {
|
for (progress.header.headers.items) |header| {
|
||||||
@@ -3144,6 +3169,9 @@ const CaptureHandler = struct {
|
|||||||
.value = try allocator.dupe(u8, header.value),
|
.value = try allocator.dupe(u8, header.value),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (progress.done) {
|
||||||
self.reset.set();
|
self.reset.set();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user