mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-10-28 22:53:28 +00:00
Emit http_request_fail notification
CDP translate this into a Network.loadingFailed. This is necessary to make sure every Network.requestWillBeSent is paired with either a Network.loadingFailed or a Network.responseReceived.
This commit is contained in:
@@ -247,6 +247,8 @@ pub const Page = struct {
|
||||
.content_type = content_type,
|
||||
.charset = mime.charset,
|
||||
.url = request_url,
|
||||
.method = opts.method,
|
||||
.reason = opts.reason,
|
||||
});
|
||||
|
||||
if (!mime.isHTML()) {
|
||||
@@ -597,6 +599,10 @@ pub const Page = struct {
|
||||
// The page.arena is safe to use here, but the transfer_arena exists
|
||||
// specifically for this type of lifetime.
|
||||
pub fn navigateFromWebAPI(self: *Page, url: []const u8, opts: NavigateOpts) !void {
|
||||
log.debug(.browser, "delayed navigation", .{
|
||||
.url = url,
|
||||
.reason = opts.reason,
|
||||
});
|
||||
self.delayed_navigation = true;
|
||||
const arena = self.session.transfer_arena;
|
||||
const navi = try arena.create(DelayedNavigation);
|
||||
|
||||
@@ -338,7 +338,11 @@ pub const XMLHttpRequest = struct {
|
||||
// dispatch request event.
|
||||
// errors are logged only.
|
||||
fn dispatchEvt(self: *XMLHttpRequest, typ: []const u8) void {
|
||||
log.debug(.script_event, "dispatch event", .{ .type = typ, .source = "xhr" });
|
||||
log.debug(.script_event, "dispatch event", .{
|
||||
.type = typ,
|
||||
.source = "xhr",
|
||||
.url = self.url,
|
||||
});
|
||||
self._dispatchEvt(typ) catch |err| {
|
||||
log.err(.app, "dispatch event error", .{ .err = err, .type = typ, .source = "xhr" });
|
||||
};
|
||||
@@ -358,7 +362,11 @@ pub const XMLHttpRequest = struct {
|
||||
typ: []const u8,
|
||||
opts: ProgressEvent.EventInit,
|
||||
) void {
|
||||
log.debug(.script_event, "dispatch progress event", .{ .type = typ, .source = "xhr" });
|
||||
log.debug(.script_event, "dispatch progress event", .{
|
||||
.type = typ,
|
||||
.source = "xhr",
|
||||
.url = self.url,
|
||||
});
|
||||
self._dispatchProgressEvent(typ, opts) catch |err| {
|
||||
log.err(.app, "dispatch progress event error", .{ .err = err, .type = typ, .source = "xhr" });
|
||||
};
|
||||
|
||||
@@ -412,11 +412,13 @@ pub fn BrowserContext(comptime CDP_T: type) type {
|
||||
}
|
||||
|
||||
pub fn networkEnable(self: *Self) !void {
|
||||
try self.cdp.browser.notification.register(.http_request_fail, self, onHttpRequestFail);
|
||||
try self.cdp.browser.notification.register(.http_request_start, self, onHttpRequestStart);
|
||||
try self.cdp.browser.notification.register(.http_request_complete, self, onHttpRequestComplete);
|
||||
}
|
||||
|
||||
pub fn networkDisable(self: *Self) void {
|
||||
self.cdp.browser.notification.unregister(.http_request_fail, self);
|
||||
self.cdp.browser.notification.unregister(.http_request_start, self);
|
||||
self.cdp.browser.notification.unregister(.http_request_complete, self);
|
||||
}
|
||||
@@ -448,6 +450,12 @@ pub fn BrowserContext(comptime CDP_T: type) type {
|
||||
return @import("domains/network.zig").httpRequestStart(self.notification_arena, self, data);
|
||||
}
|
||||
|
||||
pub fn onHttpRequestFail(ctx: *anyopaque, data: *const Notification.RequestFail) !void {
|
||||
const self: *Self = @alignCast(@ptrCast(ctx));
|
||||
defer self.resetNotificationArena();
|
||||
return @import("domains/network.zig").httpRequestFail(self.notification_arena, self, data);
|
||||
}
|
||||
|
||||
pub fn onHttpRequestComplete(ctx: *anyopaque, data: *const Notification.RequestComplete) !void {
|
||||
const self: *Self = @alignCast(@ptrCast(ctx));
|
||||
defer self.resetNotificationArena();
|
||||
|
||||
@@ -84,6 +84,24 @@ fn putAssumeCapacity(headers: *std.ArrayListUnmanaged(std.http.Header), extra: s
|
||||
return true;
|
||||
}
|
||||
|
||||
pub fn httpRequestFail(arena: Allocator, bc: anytype, request: *const Notification.RequestFail) !void {
|
||||
// Isn't possible to do a network request within a Browser (which our
|
||||
// notification is tied to), without a page.
|
||||
std.debug.assert(bc.session.page != null);
|
||||
|
||||
// all unreachable because we _have_ to have a page.
|
||||
const session_id = bc.session_id orelse unreachable;
|
||||
|
||||
// We're missing a bunch of fields, but, for now, this seems like enough
|
||||
try bc.cdp.sendEvent("Network.loadingFailed", .{
|
||||
.requestId = try std.fmt.allocPrint(arena, "REQ-{d}", .{request.id}),
|
||||
// Seems to be what chrome answers with. I assume it depends on the type of error?
|
||||
.type = "Ping",
|
||||
.errorText = request.err,
|
||||
.canceled = false,
|
||||
}, .{ .session_id = session_id });
|
||||
}
|
||||
|
||||
pub fn httpRequestStart(arena: Allocator, bc: anytype, request: *const Notification.RequestStart) !void {
|
||||
// Isn't possible to do a network request within a Browser (which our
|
||||
// notification is tied to), without a page.
|
||||
|
||||
@@ -354,6 +354,7 @@ pub const Request = struct {
|
||||
// Because of things like redirects and error handling, it is possible for
|
||||
// the notification functions to be called multiple times, so we guard them
|
||||
// with these booleans
|
||||
_notified_fail: bool,
|
||||
_notified_start: bool,
|
||||
_notified_complete: bool,
|
||||
|
||||
@@ -414,6 +415,7 @@ pub const Request = struct {
|
||||
._keepalive = false,
|
||||
._redirect_count = 0,
|
||||
._has_host_header = false,
|
||||
._notified_fail = false,
|
||||
._notified_start = false,
|
||||
._notified_complete = false,
|
||||
._connection_from_keepalive = false,
|
||||
@@ -428,6 +430,7 @@ pub const Request = struct {
|
||||
}
|
||||
|
||||
pub fn abort(self: *Request) void {
|
||||
self.requestFailed("aborted");
|
||||
const aborter = self._aborter orelse {
|
||||
self.deinit();
|
||||
return;
|
||||
@@ -555,6 +558,10 @@ pub const Request = struct {
|
||||
}
|
||||
|
||||
fn doSendSync(self: *Request, use_pool: bool) anyerror!Response {
|
||||
// https://github.com/ziglang/zig/issues/20369
|
||||
// errdefer |err| self.requestFailed(@errorName(err));
|
||||
errdefer self.requestFailed("network error");
|
||||
|
||||
if (use_pool) {
|
||||
if (self.findExistingConnection(true)) |connection| {
|
||||
self._connection = connection;
|
||||
@@ -847,6 +854,19 @@ pub const Request = struct {
|
||||
});
|
||||
}
|
||||
|
||||
fn requestFailed(self: *Request, err: []const u8) void {
|
||||
const notification = self.notification orelse return;
|
||||
if (self._notified_fail) {
|
||||
return;
|
||||
}
|
||||
self._notified_fail = true;
|
||||
notification.dispatch(.http_request_fail, &.{
|
||||
.id = self.id,
|
||||
.err = err,
|
||||
.url = self.request_uri,
|
||||
});
|
||||
}
|
||||
|
||||
fn requestCompleted(self: *Request, response: ResponseHeader) void {
|
||||
const notification = self.notification orelse return;
|
||||
if (self._notified_complete) {
|
||||
@@ -1290,6 +1310,8 @@ fn AsyncHandler(comptime H: type, comptime L: type) type {
|
||||
self.handler.onHttpResponse(err) catch {};
|
||||
// just to be safe
|
||||
self.request._keepalive = false;
|
||||
|
||||
self.request.requestFailed(@errorName(err));
|
||||
self.request.deinit();
|
||||
}
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@ pub const Notification = struct {
|
||||
page_created: List = .{},
|
||||
page_navigate: List = .{},
|
||||
page_navigated: List = .{},
|
||||
http_request_fail: List = .{},
|
||||
http_request_start: List = .{},
|
||||
http_request_complete: List = .{},
|
||||
notification_created: List = .{},
|
||||
@@ -69,6 +70,7 @@ pub const Notification = struct {
|
||||
page_created: *page.Page,
|
||||
page_navigate: *const PageNavigate,
|
||||
page_navigated: *const PageNavigated,
|
||||
http_request_fail: *const RequestFail,
|
||||
http_request_start: *const RequestStart,
|
||||
http_request_complete: *const RequestComplete,
|
||||
notification_created: *Notification,
|
||||
@@ -97,6 +99,12 @@ pub const Notification = struct {
|
||||
has_body: bool,
|
||||
};
|
||||
|
||||
pub const RequestFail = struct {
|
||||
id: usize,
|
||||
url: *const std.Uri,
|
||||
err: []const u8,
|
||||
};
|
||||
|
||||
pub const RequestComplete = struct {
|
||||
id: usize,
|
||||
url: *const std.Uri,
|
||||
|
||||
@@ -127,7 +127,6 @@ pub const Loop = struct {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// JS callbacks APIs
|
||||
// -----------------
|
||||
|
||||
@@ -255,7 +254,6 @@ pub const Loop = struct {
|
||||
}
|
||||
}.onConnect;
|
||||
|
||||
|
||||
const callback = try self.event_callback_pool.create();
|
||||
errdefer self.event_callback_pool.destroy(callback);
|
||||
callback.* = .{ .loop = self, .ctx = ctx };
|
||||
|
||||
Reference in New Issue
Block a user