mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-03-31 01:28:55 +00:00
use Response instead of Transfer in callbacks
This commit is contained in:
@@ -399,8 +399,10 @@ fn fetchRobotsThenProcessRequest(self: *Client, robots_url: [:0]const u8, req: R
|
|||||||
try entry.value_ptr.append(self.allocator, req);
|
try entry.value_ptr.append(self.allocator, req);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn robotsHeaderCallback(transfer: *Transfer) !bool {
|
fn robotsHeaderCallback(response: Response) !bool {
|
||||||
const ctx: *RobotsRequestContext = @ptrCast(@alignCast(transfer.ctx));
|
const ctx: *RobotsRequestContext = @ptrCast(@alignCast(response.ctx));
|
||||||
|
// Robots callbacks only happen on real live requests.
|
||||||
|
const transfer = response.inner.transfer;
|
||||||
|
|
||||||
if (transfer.response_header) |hdr| {
|
if (transfer.response_header) |hdr| {
|
||||||
log.debug(.browser, "robots status", .{ .status = hdr.status, .robots_url = ctx.robots_url });
|
log.debug(.browser, "robots status", .{ .status = hdr.status, .robots_url = ctx.robots_url });
|
||||||
@@ -414,8 +416,8 @@ fn robotsHeaderCallback(transfer: *Transfer) !bool {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn robotsDataCallback(transfer: *Transfer, data: []const u8) !void {
|
fn robotsDataCallback(response: Response, data: []const u8) !void {
|
||||||
const ctx: *RobotsRequestContext = @ptrCast(@alignCast(transfer.ctx));
|
const ctx: *RobotsRequestContext = @ptrCast(@alignCast(response.ctx));
|
||||||
try ctx.buffer.appendSlice(ctx.client.allocator, data);
|
try ctx.buffer.appendSlice(ctx.client.allocator, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -634,13 +636,43 @@ fn makeTransfer(self: *Client, req: Request) !*Transfer {
|
|||||||
.id = id,
|
.id = id,
|
||||||
.url = req.url,
|
.url = req.url,
|
||||||
.req = req,
|
.req = req,
|
||||||
.ctx = req.ctx,
|
|
||||||
.client = self,
|
.client = self,
|
||||||
.max_response_size = self.network.config.httpMaxResponseSize(),
|
.max_response_size = self.network.config.httpMaxResponseSize(),
|
||||||
};
|
};
|
||||||
return transfer;
|
return transfer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn requestFailed(transfer: *Transfer, err: anyerror, comptime execute_callback: bool) void {
|
||||||
|
if (transfer._notified_fail) {
|
||||||
|
// we can force a failed request within a callback, which will eventually
|
||||||
|
// result in this being called again in the more general loop. We do this
|
||||||
|
// because we can raise a more specific error inside a callback in some cases
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
transfer._notified_fail = true;
|
||||||
|
|
||||||
|
transfer.req.notification.dispatch(.http_request_fail, &.{
|
||||||
|
.transfer = transfer,
|
||||||
|
.err = err,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (execute_callback) {
|
||||||
|
transfer.req.error_callback(transfer.req.ctx, err);
|
||||||
|
} else if (transfer.req.shutdown_callback) |cb| {
|
||||||
|
cb(transfer.req.ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Same restriction as changeProxy. Should be ok since this is only called on
|
||||||
|
// BrowserContext deinit.
|
||||||
|
pub fn restoreOriginalProxy(self: *Client) !void {
|
||||||
|
try self.ensureNoActiveConnection();
|
||||||
|
|
||||||
|
self.http_proxy = self.network.config.httpProxy();
|
||||||
|
self.use_proxy = self.http_proxy != null;
|
||||||
|
}
|
||||||
|
|
||||||
fn makeRequest(self: *Client, conn: *http.Connection, transfer: *Transfer) anyerror!void {
|
fn makeRequest(self: *Client, conn: *http.Connection, transfer: *Transfer) anyerror!void {
|
||||||
{
|
{
|
||||||
// Reset per-response state for retries (auth challenge, queue).
|
// Reset per-response state for retries (auth challenge, queue).
|
||||||
@@ -674,7 +706,7 @@ fn makeRequest(self: *Client, conn: *http.Connection, transfer: *Transfer) anyer
|
|||||||
self.active += 1;
|
self.active += 1;
|
||||||
|
|
||||||
if (transfer.req.start_callback) |cb| {
|
if (transfer.req.start_callback) |cb| {
|
||||||
cb(transfer) catch |err| {
|
cb(Response.fromTransfer(transfer)) catch |err| {
|
||||||
transfer.deinit();
|
transfer.deinit();
|
||||||
return err;
|
return err;
|
||||||
};
|
};
|
||||||
@@ -742,7 +774,10 @@ fn processOneMessage(self: *Client, msg: http.Handles.MultiMessage, transfer: *T
|
|||||||
// TODO give a way to configure the number of auth retries.
|
// TODO give a way to configure the number of auth retries.
|
||||||
if (transfer._auth_challenge != null and transfer._tries < 10) {
|
if (transfer._auth_challenge != null and transfer._tries < 10) {
|
||||||
var wait_for_interception = false;
|
var wait_for_interception = false;
|
||||||
transfer.req.notification.dispatch(.http_request_auth_required, &.{ .transfer = transfer, .wait_for_interception = &wait_for_interception });
|
transfer.req.notification.dispatch(
|
||||||
|
.http_request_auth_required,
|
||||||
|
&.{ .transfer = transfer, .wait_for_interception = &wait_for_interception },
|
||||||
|
);
|
||||||
if (wait_for_interception) {
|
if (wait_for_interception) {
|
||||||
self.intercepted += 1;
|
self.intercepted += 1;
|
||||||
if (comptime IS_DEBUG) {
|
if (comptime IS_DEBUG) {
|
||||||
@@ -844,7 +879,7 @@ fn processOneMessage(self: *Client, msg: http.Handles.MultiMessage, transfer: *T
|
|||||||
// Replay buffered body through user's data_callback.
|
// Replay buffered body through user's data_callback.
|
||||||
if (transfer._stream_buffer.items.len > 0) {
|
if (transfer._stream_buffer.items.len > 0) {
|
||||||
const body = transfer._stream_buffer.items;
|
const body = transfer._stream_buffer.items;
|
||||||
try transfer.req.data_callback(transfer, body);
|
try transfer.req.data_callback(Response.fromTransfer(transfer), body);
|
||||||
|
|
||||||
transfer.req.notification.dispatch(.http_response_data, &.{
|
transfer.req.notification.dispatch(.http_response_data, &.{
|
||||||
.data = body,
|
.data = body,
|
||||||
@@ -861,7 +896,7 @@ fn processOneMessage(self: *Client, msg: http.Handles.MultiMessage, transfer: *T
|
|||||||
// will load more resources.
|
// will load more resources.
|
||||||
transfer.releaseConn();
|
transfer.releaseConn();
|
||||||
|
|
||||||
try transfer.req.done_callback(transfer.ctx);
|
try transfer.req.done_callback(transfer.req.ctx);
|
||||||
transfer.req.notification.dispatch(.http_request_done, &.{
|
transfer.req.notification.dispatch(.http_request_done, &.{
|
||||||
.transfer = transfer,
|
.transfer = transfer,
|
||||||
});
|
});
|
||||||
@@ -939,9 +974,9 @@ pub const Request = struct {
|
|||||||
// arbitrary data that can be associated with this request
|
// arbitrary data that can be associated with this request
|
||||||
ctx: *anyopaque = undefined,
|
ctx: *anyopaque = undefined,
|
||||||
|
|
||||||
start_callback: ?*const fn (transfer: *Transfer) anyerror!void = null,
|
start_callback: ?*const fn (response: Response) anyerror!void = null,
|
||||||
header_callback: *const fn (transfer: *Transfer) anyerror!bool,
|
header_callback: *const fn (response: Response) anyerror!bool,
|
||||||
data_callback: *const fn (transfer: *Transfer, data: []const u8) anyerror!void,
|
data_callback: *const fn (response: Response, data: []const u8) anyerror!void,
|
||||||
done_callback: *const fn (ctx: *anyopaque) anyerror!void,
|
done_callback: *const fn (ctx: *anyopaque) anyerror!void,
|
||||||
error_callback: *const fn (ctx: *anyopaque, err: anyerror) void,
|
error_callback: *const fn (ctx: *anyopaque, err: anyerror) void,
|
||||||
shutdown_callback: ?*const fn (ctx: *anyopaque) void = null,
|
shutdown_callback: ?*const fn (ctx: *anyopaque) void = null,
|
||||||
@@ -967,12 +1002,66 @@ pub const Request = struct {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const Response = struct {
|
||||||
|
ctx: *anyopaque,
|
||||||
|
inner: union(enum) {
|
||||||
|
transfer: *Transfer,
|
||||||
|
},
|
||||||
|
|
||||||
|
pub fn fromTransfer(transfer: *Transfer) Response {
|
||||||
|
return .{ .ctx = transfer.req.ctx, .inner = .{ .transfer = transfer } };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn status(self: Response) ?u16 {
|
||||||
|
return switch (self.inner) {
|
||||||
|
.transfer => |t| if (t.response_header) |rh| rh.status else null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn contentType(self: Response) ?[]const u8 {
|
||||||
|
return switch (self.inner) {
|
||||||
|
.transfer => |t| if (t.response_header) |*rh| rh.contentType() else null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn contentLength(self: Response) ?u32 {
|
||||||
|
return switch (self.inner) {
|
||||||
|
.transfer => |t| t.getContentLength(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn redirectCount(self: Response) ?u32 {
|
||||||
|
return switch (self.inner) {
|
||||||
|
.transfer => |t| if (t.response_header) |rh| rh.redirect_count else null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn url(self: Response) [:0]const u8 {
|
||||||
|
return switch (self.inner) {
|
||||||
|
.transfer => |t| t.url,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Headers Iterator.
|
||||||
|
|
||||||
|
pub fn abort(self: Response, err: anyerror) void {
|
||||||
|
switch (self.inner) {
|
||||||
|
.transfer => |t| t.abort(err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn terminate(self: Response) void {
|
||||||
|
switch (self.inner) {
|
||||||
|
.transfer => |t| t.terminate(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
pub const Transfer = struct {
|
pub const Transfer = struct {
|
||||||
arena: ArenaAllocator,
|
arena: ArenaAllocator,
|
||||||
id: u32 = 0,
|
id: u32 = 0,
|
||||||
req: Request,
|
req: Request,
|
||||||
url: [:0]const u8,
|
url: [:0]const u8,
|
||||||
ctx: *anyopaque, // copied from req.ctx to make it easier for callback handlers
|
|
||||||
client: *Client,
|
client: *Client,
|
||||||
// total bytes received in the response, including the response status line,
|
// total bytes received in the response, including the response status line,
|
||||||
// the headers, and the [encoded] body.
|
// the headers, and the [encoded] body.
|
||||||
@@ -1065,7 +1154,7 @@ pub const Transfer = struct {
|
|||||||
// as abort (doesn't send a notification, doesn't invoke an error callback)
|
// as abort (doesn't send a notification, doesn't invoke an error callback)
|
||||||
fn kill(self: *Transfer) void {
|
fn kill(self: *Transfer) void {
|
||||||
if (self.req.shutdown_callback) |cb| {
|
if (self.req.shutdown_callback) |cb| {
|
||||||
cb(self.ctx);
|
cb(self.req.ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self._performing or self.client.performing) {
|
if (self._performing or self.client.performing) {
|
||||||
@@ -1101,7 +1190,7 @@ pub const Transfer = struct {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (execute_callback) {
|
if (execute_callback) {
|
||||||
self.req.error_callback(self.ctx, err);
|
self.req.error_callback(self.req.ctx, err);
|
||||||
} else if (self.req.shutdown_callback) |cb| {
|
} else if (self.req.shutdown_callback) |cb| {
|
||||||
cb(self.ctx);
|
cb(self.ctx);
|
||||||
}
|
}
|
||||||
@@ -1342,7 +1431,7 @@ pub const Transfer = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const proceed = transfer.req.header_callback(transfer) catch |err| {
|
const proceed = transfer.req.header_callback(Response.fromTransfer(transfer)) catch |err| {
|
||||||
log.err(.http, "header_callback", .{ .err = err, .req = transfer });
|
log.err(.http, "header_callback", .{ .err = err, .req = transfer });
|
||||||
return err;
|
return err;
|
||||||
};
|
};
|
||||||
@@ -1449,7 +1538,7 @@ pub const Transfer = struct {
|
|||||||
fn _fulfill(transfer: *Transfer, status: u16, headers: []const http.Header, body: ?[]const u8) !void {
|
fn _fulfill(transfer: *Transfer, status: u16, headers: []const http.Header, body: ?[]const u8) !void {
|
||||||
const req = &transfer.req;
|
const req = &transfer.req;
|
||||||
if (req.start_callback) |cb| {
|
if (req.start_callback) |cb| {
|
||||||
try cb(transfer);
|
try cb(Response.fromTransfer(transfer));
|
||||||
}
|
}
|
||||||
|
|
||||||
transfer.response_header = .{
|
transfer.response_header = .{
|
||||||
@@ -1468,13 +1557,13 @@ pub const Transfer = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
lp.assert(transfer._header_done_called == false, "Transfer.fulfill header_done_called", .{});
|
lp.assert(transfer._header_done_called == false, "Transfer.fulfill header_done_called", .{});
|
||||||
if (try req.header_callback(transfer) == false) {
|
if (try req.header_callback(Response.fromTransfer(transfer)) == false) {
|
||||||
transfer.abort(error.Abort);
|
transfer.abort(error.Abort);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (body) |b| {
|
if (body) |b| {
|
||||||
try req.data_callback(transfer, b);
|
try req.data_callback(Response.fromTransfer(transfer), b);
|
||||||
}
|
}
|
||||||
|
|
||||||
try req.done_callback(req.ctx);
|
try req.done_callback(req.ctx);
|
||||||
@@ -1511,10 +1600,10 @@ pub const Transfer = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const Noop = struct {
|
const Noop = struct {
|
||||||
fn headerCallback(_: *Transfer) !bool {
|
fn headerCallback(_: Response) !bool {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
fn dataCallback(_: *Transfer, _: []const u8) !void {}
|
fn dataCallback(_: Response, _: []const u8) !void {}
|
||||||
fn doneCallback(_: *anyopaque) !void {}
|
fn doneCallback(_: *anyopaque) !void {}
|
||||||
fn errorCallback(_: *anyopaque, _: anyerror) void {}
|
fn errorCallback(_: *anyopaque, _: anyerror) void {}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -854,12 +854,10 @@ fn notifyParentLoadComplete(self: *Page) void {
|
|||||||
parent.iframeCompletedLoading(self.iframe.?);
|
parent.iframeCompletedLoading(self.iframe.?);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pageHeaderDoneCallback(transfer: *HttpClient.Transfer) !bool {
|
fn pageHeaderDoneCallback(response: HttpClient.Response) !bool {
|
||||||
var self: *Page = @ptrCast(@alignCast(transfer.ctx));
|
var self: *Page = @ptrCast(@alignCast(response.ctx));
|
||||||
|
|
||||||
const header = &transfer.response_header.?;
|
const response_url = response.url();
|
||||||
|
|
||||||
const response_url = std.mem.span(header.url);
|
|
||||||
if (std.mem.eql(u8, response_url, self.url) == false) {
|
if (std.mem.eql(u8, response_url, self.url) == false) {
|
||||||
// would be different than self.url in the case of a redirect
|
// would be different than self.url in the case of a redirect
|
||||||
self.url = try self.arena.dupeZ(u8, response_url);
|
self.url = try self.arena.dupeZ(u8, response_url);
|
||||||
@@ -873,8 +871,8 @@ fn pageHeaderDoneCallback(transfer: *HttpClient.Transfer) !bool {
|
|||||||
if (comptime IS_DEBUG) {
|
if (comptime IS_DEBUG) {
|
||||||
log.debug(.page, "navigate header", .{
|
log.debug(.page, "navigate header", .{
|
||||||
.url = self.url,
|
.url = self.url,
|
||||||
.status = header.status,
|
.status = response.status(),
|
||||||
.content_type = header.contentType(),
|
.content_type = response.contentType(),
|
||||||
.type = self._type,
|
.type = self._type,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -882,14 +880,14 @@ fn pageHeaderDoneCallback(transfer: *HttpClient.Transfer) !bool {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pageDataCallback(transfer: *HttpClient.Transfer, data: []const u8) !void {
|
fn pageDataCallback(response: HttpClient.Response, data: []const u8) !void {
|
||||||
var self: *Page = @ptrCast(@alignCast(transfer.ctx));
|
var self: *Page = @ptrCast(@alignCast(response.ctx));
|
||||||
|
|
||||||
if (self._parse_state == .pre) {
|
if (self._parse_state == .pre) {
|
||||||
// we lazily do this, because we might need the first chunk of data
|
// we lazily do this, because we might need the first chunk of data
|
||||||
// to sniff the content type
|
// to sniff the content type
|
||||||
var mime: Mime = blk: {
|
var mime: Mime = blk: {
|
||||||
if (transfer.response_header.?.contentType()) |ct| {
|
if (response.contentType()) |ct| {
|
||||||
break :blk try Mime.parse(ct);
|
break :blk try Mime.parse(ct);
|
||||||
}
|
}
|
||||||
break :blk Mime.sniff(data);
|
break :blk Mime.sniff(data);
|
||||||
|
|||||||
@@ -694,82 +694,85 @@ pub const Script = struct {
|
|||||||
self.manager.page.releaseArena(self.arena);
|
self.manager.page.releaseArena(self.arena);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn startCallback(transfer: *HttpClient.Transfer) !void {
|
fn startCallback(response: HttpClient.Response) !void {
|
||||||
log.debug(.http, "script fetch start", .{ .req = transfer });
|
log.debug(.http, "script fetch start", .{ .req = response });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn headerCallback(transfer: *HttpClient.Transfer) !bool {
|
fn headerCallback(response: HttpClient.Response) !bool {
|
||||||
const self: *Script = @ptrCast(@alignCast(transfer.ctx));
|
const self: *Script = @ptrCast(@alignCast(response.ctx));
|
||||||
const header = &transfer.response_header.?;
|
|
||||||
self.status = header.status;
|
self.status = response.status().?;
|
||||||
if (header.status != 200) {
|
if (response.status() != 200) {
|
||||||
log.info(.http, "script header", .{
|
log.info(.http, "script header", .{
|
||||||
.req = transfer,
|
.req = response,
|
||||||
.status = header.status,
|
.status = response.status(),
|
||||||
.content_type = header.contentType(),
|
.content_type = response.contentType(),
|
||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (comptime IS_DEBUG) {
|
if (comptime IS_DEBUG) {
|
||||||
log.debug(.http, "script header", .{
|
log.debug(.http, "script header", .{
|
||||||
.req = transfer,
|
.req = response,
|
||||||
.status = header.status,
|
.status = response.status(),
|
||||||
.content_type = header.contentType(),
|
.content_type = response.contentType(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
switch (response.inner) {
|
||||||
// temp debug, trying to figure out why the next assert sometimes
|
.transfer => |transfer| {
|
||||||
// fails. Is the buffer just corrupt or is headerCallback really
|
// temp debug, trying to figure out why the next assert sometimes
|
||||||
// being called twice?
|
// fails. Is the buffer just corrupt or is headerCallback really
|
||||||
lp.assert(self.header_callback_called == false, "ScriptManager.Header recall", .{
|
// being called twice?
|
||||||
.m = @tagName(std.meta.activeTag(self.mode)),
|
lp.assert(self.header_callback_called == false, "ScriptManager.Header recall", .{
|
||||||
.a1 = self.debug_transfer_id,
|
.m = @tagName(std.meta.activeTag(self.mode)),
|
||||||
.a2 = self.debug_transfer_tries,
|
.a1 = self.debug_transfer_id,
|
||||||
.a3 = self.debug_transfer_aborted,
|
.a2 = self.debug_transfer_tries,
|
||||||
.a4 = self.debug_transfer_bytes_received,
|
.a3 = self.debug_transfer_aborted,
|
||||||
.a5 = self.debug_transfer_notified_fail,
|
.a4 = self.debug_transfer_bytes_received,
|
||||||
.a7 = self.debug_transfer_intercept_state,
|
.a5 = self.debug_transfer_notified_fail,
|
||||||
.a8 = self.debug_transfer_auth_challenge,
|
.a7 = self.debug_transfer_intercept_state,
|
||||||
.a9 = self.debug_transfer_easy_id,
|
.a8 = self.debug_transfer_auth_challenge,
|
||||||
.b1 = transfer.id,
|
.a9 = self.debug_transfer_easy_id,
|
||||||
.b2 = transfer._tries,
|
.b1 = transfer.id,
|
||||||
.b3 = transfer.aborted,
|
.b2 = transfer._tries,
|
||||||
.b4 = transfer.bytes_received,
|
.b3 = transfer.aborted,
|
||||||
.b5 = transfer._notified_fail,
|
.b4 = transfer.bytes_received,
|
||||||
.b7 = @intFromEnum(transfer._intercept_state),
|
.b5 = transfer._notified_fail,
|
||||||
.b8 = transfer._auth_challenge != null,
|
.b7 = @intFromEnum(transfer._intercept_state),
|
||||||
.b9 = if (transfer._conn) |c| @intFromPtr(c._easy) else 0,
|
.b8 = transfer._auth_challenge != null,
|
||||||
});
|
.b9 = if (transfer._conn) |c| @intFromPtr(c._easy) else 0,
|
||||||
self.header_callback_called = true;
|
});
|
||||||
self.debug_transfer_id = transfer.id;
|
self.header_callback_called = true;
|
||||||
self.debug_transfer_tries = transfer._tries;
|
self.debug_transfer_id = transfer.id;
|
||||||
self.debug_transfer_aborted = transfer.aborted;
|
self.debug_transfer_tries = transfer._tries;
|
||||||
self.debug_transfer_bytes_received = transfer.bytes_received;
|
self.debug_transfer_aborted = transfer.aborted;
|
||||||
self.debug_transfer_notified_fail = transfer._notified_fail;
|
self.debug_transfer_bytes_received = transfer.bytes_received;
|
||||||
self.debug_transfer_intercept_state = @intFromEnum(transfer._intercept_state);
|
self.debug_transfer_notified_fail = transfer._notified_fail;
|
||||||
self.debug_transfer_auth_challenge = transfer._auth_challenge != null;
|
self.debug_transfer_intercept_state = @intFromEnum(transfer._intercept_state);
|
||||||
self.debug_transfer_easy_id = if (transfer._conn) |c| @intFromPtr(c._easy) else 0;
|
self.debug_transfer_auth_challenge = transfer._auth_challenge != null;
|
||||||
|
self.debug_transfer_easy_id = if (transfer._conn) |c| @intFromPtr(c._easy) else 0;
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
lp.assert(self.source.remote.capacity == 0, "ScriptManager.Header buffer", .{ .capacity = self.source.remote.capacity });
|
lp.assert(self.source.remote.capacity == 0, "ScriptManager.Header buffer", .{ .capacity = self.source.remote.capacity });
|
||||||
var buffer: std.ArrayList(u8) = .empty;
|
var buffer: std.ArrayList(u8) = .empty;
|
||||||
if (transfer.getContentLength()) |cl| {
|
if (response.contentLength()) |cl| {
|
||||||
try buffer.ensureTotalCapacity(self.arena, cl);
|
try buffer.ensureTotalCapacity(self.arena, cl);
|
||||||
}
|
}
|
||||||
self.source = .{ .remote = buffer };
|
self.source = .{ .remote = buffer };
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dataCallback(transfer: *HttpClient.Transfer, data: []const u8) !void {
|
fn dataCallback(response: HttpClient.Response, data: []const u8) !void {
|
||||||
const self: *Script = @ptrCast(@alignCast(transfer.ctx));
|
const self: *Script = @ptrCast(@alignCast(response.ctx));
|
||||||
self._dataCallback(transfer, data) catch |err| {
|
self._dataCallback(response, data) catch |err| {
|
||||||
log.err(.http, "SM.dataCallback", .{ .err = err, .transfer = transfer, .len = data.len });
|
log.err(.http, "SM.dataCallback", .{ .err = err, .transfer = response, .len = data.len });
|
||||||
return err;
|
return err;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
fn _dataCallback(self: *Script, _: *HttpClient.Transfer, data: []const u8) !void {
|
|
||||||
|
fn _dataCallback(self: *Script, _: HttpClient.Response, data: []const u8) !void {
|
||||||
try self.source.remote.appendSlice(self.arena, data);
|
try self.source.remote.appendSlice(self.arena, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -127,16 +127,16 @@ fn handleBlobUrl(url: []const u8, resolver: js.PromiseResolver, page: *Page) !js
|
|||||||
return resolver.promise();
|
return resolver.promise();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn httpStartCallback(transfer: *HttpClient.Transfer) !void {
|
fn httpStartCallback(response: HttpClient.Response) !void {
|
||||||
const self: *Fetch = @ptrCast(@alignCast(transfer.ctx));
|
const self: *Fetch = @ptrCast(@alignCast(response.ctx));
|
||||||
if (comptime IS_DEBUG) {
|
if (comptime IS_DEBUG) {
|
||||||
log.debug(.http, "request start", .{ .url = self._url, .source = "fetch" });
|
log.debug(.http, "request start", .{ .url = self._url, .source = "fetch" });
|
||||||
}
|
}
|
||||||
self._response._transfer = transfer;
|
self._response._http_response = response;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn httpHeaderDoneCallback(transfer: *HttpClient.Transfer) !bool {
|
fn httpHeaderDoneCallback(response: HttpClient.Response) !bool {
|
||||||
const self: *Fetch = @ptrCast(@alignCast(transfer.ctx));
|
const self: *Fetch = @ptrCast(@alignCast(response.ctx));
|
||||||
|
|
||||||
if (self._signal) |signal| {
|
if (self._signal) |signal| {
|
||||||
if (signal._aborted) {
|
if (signal._aborted) {
|
||||||
@@ -145,25 +145,24 @@ fn httpHeaderDoneCallback(transfer: *HttpClient.Transfer) !bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const arena = self._response._arena;
|
const arena = self._response._arena;
|
||||||
if (transfer.getContentLength()) |cl| {
|
if (response.contentLength()) |cl| {
|
||||||
try self._buf.ensureTotalCapacity(arena, cl);
|
try self._buf.ensureTotalCapacity(arena, cl);
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = self._response;
|
const res = self._response;
|
||||||
const header = transfer.response_header.?;
|
|
||||||
|
|
||||||
if (comptime IS_DEBUG) {
|
if (comptime IS_DEBUG) {
|
||||||
log.debug(.http, "request header", .{
|
log.debug(.http, "request header", .{
|
||||||
.source = "fetch",
|
.source = "fetch",
|
||||||
.url = self._url,
|
.url = self._url,
|
||||||
.status = header.status,
|
.status = response.status(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
res._status = header.status;
|
res._status = response.status().?;
|
||||||
res._status_text = std.http.Status.phrase(@enumFromInt(header.status)) orelse "";
|
res._status_text = std.http.Status.phrase(@enumFromInt(response.status().?)) orelse "";
|
||||||
res._url = try arena.dupeZ(u8, std.mem.span(header.url));
|
res._url = try arena.dupeZ(u8, response.url());
|
||||||
res._is_redirected = header.redirect_count > 0;
|
res._is_redirected = response.redirectCount().? > 0;
|
||||||
|
|
||||||
// Determine response type based on origin comparison
|
// Determine response type based on origin comparison
|
||||||
const page_origin = URL.getOrigin(arena, self._page.url) catch null;
|
const page_origin = URL.getOrigin(arena, self._page.url) catch null;
|
||||||
@@ -183,16 +182,17 @@ fn httpHeaderDoneCallback(transfer: *HttpClient.Transfer) !bool {
|
|||||||
res._type = .basic;
|
res._type = .basic;
|
||||||
}
|
}
|
||||||
|
|
||||||
var it = transfer.responseHeaderIterator();
|
// TODO: Header Iterator
|
||||||
while (it.next()) |hdr| {
|
// var it = transfer.responseHeaderIterator();
|
||||||
try res._headers.append(hdr.name, hdr.value, self._page);
|
// while (it.next()) |hdr| {
|
||||||
}
|
// try res._headers.append(hdr.name, hdr.value, self._page);
|
||||||
|
// }
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn httpDataCallback(transfer: *HttpClient.Transfer, data: []const u8) !void {
|
fn httpDataCallback(response: HttpClient.Response, data: []const u8) !void {
|
||||||
const self: *Fetch = @ptrCast(@alignCast(transfer.ctx));
|
const self: *Fetch = @ptrCast(@alignCast(response.ctx));
|
||||||
|
|
||||||
// Check if aborted
|
// Check if aborted
|
||||||
if (self._signal) |signal| {
|
if (self._signal) |signal| {
|
||||||
@@ -207,7 +207,7 @@ fn httpDataCallback(transfer: *HttpClient.Transfer, data: []const u8) !void {
|
|||||||
fn httpDoneCallback(ctx: *anyopaque) !void {
|
fn httpDoneCallback(ctx: *anyopaque) !void {
|
||||||
const self: *Fetch = @ptrCast(@alignCast(ctx));
|
const self: *Fetch = @ptrCast(@alignCast(ctx));
|
||||||
var response = self._response;
|
var response = self._response;
|
||||||
response._transfer = null;
|
response._http_response = null;
|
||||||
response._body = self._buf.items;
|
response._body = self._buf.items;
|
||||||
|
|
||||||
log.info(.http, "request complete", .{
|
log.info(.http, "request complete", .{
|
||||||
@@ -230,7 +230,7 @@ fn httpErrorCallback(ctx: *anyopaque, _: anyerror) void {
|
|||||||
const self: *Fetch = @ptrCast(@alignCast(ctx));
|
const self: *Fetch = @ptrCast(@alignCast(ctx));
|
||||||
|
|
||||||
var response = self._response;
|
var response = self._response;
|
||||||
response._transfer = null;
|
response._http_response = null;
|
||||||
// the response is only passed on v8 on success, if we're here, it's safe to
|
// the response is only passed on v8 on success, if we're here, it's safe to
|
||||||
// clear this. (defer since `self is in the response's arena).
|
// clear this. (defer since `self is in the response's arena).
|
||||||
|
|
||||||
@@ -256,7 +256,7 @@ fn httpShutdownCallback(ctx: *anyopaque) void {
|
|||||||
|
|
||||||
if (self._owns_response) {
|
if (self._owns_response) {
|
||||||
var response = self._response;
|
var response = self._response;
|
||||||
response._transfer = null;
|
response._http_response = null;
|
||||||
response.deinit(self._page._session);
|
response.deinit(self._page._session);
|
||||||
// Do not access `self` after this point: the Fetch struct was
|
// Do not access `self` after this point: the Fetch struct was
|
||||||
// allocated from response._arena which has been released.
|
// allocated from response._arena which has been released.
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ _type: Type,
|
|||||||
_status_text: []const u8,
|
_status_text: []const u8,
|
||||||
_url: [:0]const u8,
|
_url: [:0]const u8,
|
||||||
_is_redirected: bool,
|
_is_redirected: bool,
|
||||||
_transfer: ?*HttpClient.Transfer = null,
|
_http_response: ?HttpClient.Response = null,
|
||||||
|
|
||||||
const InitOpts = struct {
|
const InitOpts = struct {
|
||||||
status: u16 = 200,
|
status: u16 = 200,
|
||||||
@@ -81,9 +81,9 @@ pub fn init(body_: ?[]const u8, opts_: ?InitOpts, page: *Page) !*Response {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *Response, session: *Session) void {
|
pub fn deinit(self: *Response, session: *Session) void {
|
||||||
if (self._transfer) |transfer| {
|
if (self._http_response) |resp| {
|
||||||
transfer.abort(error.Abort);
|
resp.abort(error.Abort);
|
||||||
self._transfer = null;
|
self._http_response = null;
|
||||||
}
|
}
|
||||||
session.releaseArena(self._arena);
|
session.releaseArena(self._arena);
|
||||||
}
|
}
|
||||||
@@ -191,7 +191,7 @@ pub fn clone(self: *const Response, page: *Page) !*Response {
|
|||||||
._type = self._type,
|
._type = self._type,
|
||||||
._is_redirected = self._is_redirected,
|
._is_redirected = self._is_redirected,
|
||||||
._headers = try Headers.init(.{ .obj = self._headers }, page),
|
._headers = try Headers.init(.{ .obj = self._headers }, page),
|
||||||
._transfer = null,
|
._http_response = null,
|
||||||
};
|
};
|
||||||
return cloned;
|
return cloned;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ _rc: lp.RC(u8) = .{},
|
|||||||
_page: *Page,
|
_page: *Page,
|
||||||
_proto: *XMLHttpRequestEventTarget,
|
_proto: *XMLHttpRequestEventTarget,
|
||||||
_arena: Allocator,
|
_arena: Allocator,
|
||||||
_transfer: ?*HttpClient.Transfer = null,
|
_http_response: ?HttpClient.Response = null,
|
||||||
|
|
||||||
_url: [:0]const u8 = "",
|
_url: [:0]const u8 = "",
|
||||||
_method: net_http.Method = .GET,
|
_method: net_http.Method = .GET,
|
||||||
@@ -99,9 +99,9 @@ pub fn init(page: *Page) !*XMLHttpRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *XMLHttpRequest, session: *Session) void {
|
pub fn deinit(self: *XMLHttpRequest, session: *Session) void {
|
||||||
if (self._transfer) |transfer| {
|
if (self._http_response) |resp| {
|
||||||
transfer.abort(error.Abort);
|
resp.abort(error.Abort);
|
||||||
self._transfer = null;
|
self._http_response = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self._on_ready_state_change) |func| {
|
if (self._on_ready_state_change) |func| {
|
||||||
@@ -175,9 +175,9 @@ pub fn setWithCredentials(self: *XMLHttpRequest, value: bool) !void {
|
|||||||
// TODO: url should be a union, as it can be multiple things
|
// TODO: url should be a union, as it can be multiple things
|
||||||
pub fn open(self: *XMLHttpRequest, method_: []const u8, url: [:0]const u8) !void {
|
pub fn open(self: *XMLHttpRequest, method_: []const u8, url: [:0]const u8) !void {
|
||||||
// Abort any in-progress request
|
// Abort any in-progress request
|
||||||
if (self._transfer) |transfer| {
|
if (self._http_response) |transfer| {
|
||||||
transfer.abort(error.Abort);
|
transfer.abort(error.Abort);
|
||||||
self._transfer = null;
|
self._http_response = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset internal state
|
// Reset internal state
|
||||||
@@ -387,35 +387,33 @@ pub fn getResponseXML(self: *XMLHttpRequest, page: *Page) !?*Node.Document {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn httpStartCallback(transfer: *HttpClient.Transfer) !void {
|
fn httpStartCallback(response: HttpClient.Response) !void {
|
||||||
const self: *XMLHttpRequest = @ptrCast(@alignCast(transfer.ctx));
|
const self: *XMLHttpRequest = @ptrCast(@alignCast(response.ctx));
|
||||||
if (comptime IS_DEBUG) {
|
if (comptime IS_DEBUG) {
|
||||||
log.debug(.http, "request start", .{ .method = self._method, .url = self._url, .source = "xhr" });
|
log.debug(.http, "request start", .{ .method = self._method, .url = self._url, .source = "xhr" });
|
||||||
}
|
}
|
||||||
self._transfer = transfer;
|
self._http_response = response;
|
||||||
self.acquireRef();
|
self.acquireRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn httpHeaderCallback(transfer: *HttpClient.Transfer, header: net_http.Header) !void {
|
fn httpHeaderCallback(response: HttpClient.Response, header: net_http.Header) !void {
|
||||||
const self: *XMLHttpRequest = @ptrCast(@alignCast(transfer.ctx));
|
const self: *XMLHttpRequest = @ptrCast(@alignCast(response.ctx));
|
||||||
const joined = try std.fmt.allocPrint(self._arena, "{s}: {s}", .{ header.name, header.value });
|
const joined = try std.fmt.allocPrint(self._arena, "{s}: {s}", .{ header.name, header.value });
|
||||||
try self._response_headers.append(self._arena, joined);
|
try self._response_headers.append(self._arena, joined);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn httpHeaderDoneCallback(transfer: *HttpClient.Transfer) !bool {
|
fn httpHeaderDoneCallback(response: HttpClient.Response) !bool {
|
||||||
const self: *XMLHttpRequest = @ptrCast(@alignCast(transfer.ctx));
|
const self: *XMLHttpRequest = @ptrCast(@alignCast(response.ctx));
|
||||||
|
|
||||||
const header = &transfer.response_header.?;
|
|
||||||
|
|
||||||
if (comptime IS_DEBUG) {
|
if (comptime IS_DEBUG) {
|
||||||
log.debug(.http, "request header", .{
|
log.debug(.http, "request header", .{
|
||||||
.source = "xhr",
|
.source = "xhr",
|
||||||
.url = self._url,
|
.url = self._url,
|
||||||
.status = header.status,
|
.status = response.status(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header.contentType()) |ct| {
|
if (response.contentType()) |ct| {
|
||||||
self._response_mime = Mime.parse(ct) catch |e| {
|
self._response_mime = Mime.parse(ct) catch |e| {
|
||||||
log.info(.http, "invalid content type", .{
|
log.info(.http, "invalid content type", .{
|
||||||
.content_Type = ct,
|
.content_Type = ct,
|
||||||
@@ -426,18 +424,19 @@ fn httpHeaderDoneCallback(transfer: *HttpClient.Transfer) !bool {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
var it = transfer.responseHeaderIterator();
|
// TODO: Header Iterator
|
||||||
while (it.next()) |hdr| {
|
// var it = transfer.responseHeaderIterator();
|
||||||
const joined = try std.fmt.allocPrint(self._arena, "{s}: {s}", .{ hdr.name, hdr.value });
|
// while (it.next()) |hdr| {
|
||||||
try self._response_headers.append(self._arena, joined);
|
// const joined = try std.fmt.allocPrint(self._arena, "{s}: {s}", .{ hdr.name, hdr.value });
|
||||||
}
|
// try self._response_headers.append(self._arena, joined);
|
||||||
|
// }
|
||||||
|
|
||||||
self._response_status = header.status;
|
self._response_status = response.status().?;
|
||||||
if (transfer.getContentLength()) |cl| {
|
if (response.contentLength()) |cl| {
|
||||||
self._response_len = cl;
|
self._response_len = cl;
|
||||||
try self._response_data.ensureTotalCapacity(self._arena, cl);
|
try self._response_data.ensureTotalCapacity(self._arena, cl);
|
||||||
}
|
}
|
||||||
self._response_url = try self._arena.dupeZ(u8, std.mem.span(header.url));
|
self._response_url = try self._arena.dupeZ(u8, response.url());
|
||||||
|
|
||||||
const page = self._page;
|
const page = self._page;
|
||||||
|
|
||||||
@@ -452,8 +451,8 @@ fn httpHeaderDoneCallback(transfer: *HttpClient.Transfer) !bool {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn httpDataCallback(transfer: *HttpClient.Transfer, data: []const u8) !void {
|
fn httpDataCallback(response: HttpClient.Response, data: []const u8) !void {
|
||||||
const self: *XMLHttpRequest = @ptrCast(@alignCast(transfer.ctx));
|
const self: *XMLHttpRequest = @ptrCast(@alignCast(response.ctx));
|
||||||
try self._response_data.appendSlice(self._arena, data);
|
try self._response_data.appendSlice(self._arena, data);
|
||||||
|
|
||||||
const page = self._page;
|
const page = self._page;
|
||||||
@@ -476,7 +475,7 @@ fn httpDoneCallback(ctx: *anyopaque) !void {
|
|||||||
|
|
||||||
// Not that the request is done, the http/client will free the transfer
|
// Not that the request is done, the http/client will free the transfer
|
||||||
// object. It isn't safe to keep it around.
|
// object. It isn't safe to keep it around.
|
||||||
self._transfer = null;
|
self._http_response = null;
|
||||||
|
|
||||||
const page = self._page;
|
const page = self._page;
|
||||||
|
|
||||||
@@ -499,22 +498,22 @@ fn httpErrorCallback(ctx: *anyopaque, err: anyerror) void {
|
|||||||
const self: *XMLHttpRequest = @ptrCast(@alignCast(ctx));
|
const self: *XMLHttpRequest = @ptrCast(@alignCast(ctx));
|
||||||
// http client will close it after an error, it isn't safe to keep around
|
// http client will close it after an error, it isn't safe to keep around
|
||||||
self.handleError(err);
|
self.handleError(err);
|
||||||
if (self._transfer != null) {
|
if (self._http_response != null) {
|
||||||
self._transfer = null;
|
self._http_response = null;
|
||||||
self.releaseRef(self._page._session);
|
self.releaseRef(self._page._session);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn httpShutdownCallback(ctx: *anyopaque) void {
|
fn httpShutdownCallback(ctx: *anyopaque) void {
|
||||||
const self: *XMLHttpRequest = @ptrCast(@alignCast(ctx));
|
const self: *XMLHttpRequest = @ptrCast(@alignCast(ctx));
|
||||||
self._transfer = null;
|
self._http_response = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn abort(self: *XMLHttpRequest) void {
|
pub fn abort(self: *XMLHttpRequest) void {
|
||||||
self.handleError(error.Abort);
|
self.handleError(error.Abort);
|
||||||
if (self._transfer) |transfer| {
|
if (self._http_response) |resp| {
|
||||||
self._transfer = null;
|
resp.abort(error.Abort);
|
||||||
transfer.abort(error.Abort);
|
self._http_response = null;
|
||||||
self.releaseRef(self._page._session);
|
self.releaseRef(self._page._session);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user