mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-02-04 14:33:47 +00:00
Enable blocking auth request interception
This commit is contained in:
@@ -89,7 +89,7 @@ pub fn init(page: *Page) !*XMLHttpRequest {
|
|||||||
|
|
||||||
pub fn deinit(self: *XMLHttpRequest) void {
|
pub fn deinit(self: *XMLHttpRequest) void {
|
||||||
if (self.transfer) |transfer| {
|
if (self.transfer) |transfer| {
|
||||||
transfer.abort();
|
transfer.abort(error.Abort);
|
||||||
self.transfer = null;
|
self.transfer = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -115,7 +115,7 @@ pub fn setOnReadyStateChange(self: *XMLHttpRequest, cb_: ?js.Function) !void {
|
|||||||
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._transfer) |transfer| {
|
||||||
transfer.abort();
|
transfer.abort(error.Abort);
|
||||||
self._transfer = null;
|
self._transfer = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -373,7 +373,7 @@ fn httpErrorCallback(ctx: *anyopaque, err: anyerror) void {
|
|||||||
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._transfer) |transfer| {
|
||||||
transfer.abort();
|
transfer.abort(error.Abort);
|
||||||
self._transfer = null;
|
self._transfer = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -408,7 +408,7 @@ pub fn BrowserContext(comptime CDP_T: type) type {
|
|||||||
// abort all intercepted requests before closing the sesion/page
|
// abort all intercepted requests before closing the sesion/page
|
||||||
// since some of these might callback into the page/scriptmanager
|
// since some of these might callback into the page/scriptmanager
|
||||||
for (self.intercept_state.pendingTransfers()) |transfer| {
|
for (self.intercept_state.pendingTransfers()) |transfer| {
|
||||||
transfer.abort();
|
transfer.abort(error.ClientDisconnect);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the session has a page, we need to clear it first. The page
|
// If the session has a page, we need to clear it first. The page
|
||||||
|
|||||||
@@ -241,16 +241,22 @@ pub fn request(self: *Client, req: Request) !void {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (try self.waitForInterceptedResponse(transfer)) {
|
||||||
|
return self.process(transfer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn waitForInterceptedResponse(self: *Client, transfer: *Transfer) !bool {
|
||||||
// The request was intercepted and is blocking. This is messy, but our
|
// The request was intercepted and is blocking. This is messy, but our
|
||||||
// callers, the ScriptManager -> Page, don't have a great way to stop the
|
// callers, the ScriptManager -> Page, don't have a great way to stop the
|
||||||
// parser and return control to the CDP server to wait for the interception
|
// parser and return control to the CDP server to wait for the interception
|
||||||
// response. We have some information on the CDPClient, so we'll do the
|
// response. We have some information on the CDPClient, so we'll do the
|
||||||
// blocking here. (This is a bit of a legacy thing. Initially the Client)
|
// blocking here. (This is a bit of a legacy thing. Initially the Client
|
||||||
// had a 'extra_socket' that it could monitor. It was named 'extra_socket'
|
// had a 'extra_socket' that it could monitor. It was named 'extra_socket'
|
||||||
// to appear generic, but really, that 'extra_socket' was always the CDP
|
// to appear generic, but really, that 'extra_socket' was always the CDP
|
||||||
// socket that we could monitor in libcurm. Because we already had
|
// socket. Because we already had the "extra_socket" here, it was easier to
|
||||||
// the "extra_socket" here, it was easier just to make it even more CDP-
|
// make it even more CDP- aware and turn `extra_socket: socket_t` into the
|
||||||
// aware and turn `extra_socket: socket_t` into the current CDPClient).
|
// current CDPClient and do the blocking here).
|
||||||
const cdp_client = self.cdp_client.?;
|
const cdp_client = self.cdp_client.?;
|
||||||
const ctx = cdp_client.ctx;
|
const ctx = cdp_client.ctx;
|
||||||
|
|
||||||
@@ -258,6 +264,8 @@ pub fn request(self: *Client, req: Request) !void {
|
|||||||
return error.BlockingInterceptFailure;
|
return error.BlockingInterceptFailure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defer _ = cdp_client.blocking_read_end(ctx);
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (cdp_client.blocking_read(ctx) == false) {
|
if (cdp_client.blocking_read(ctx) == false) {
|
||||||
return error.BlockingInterceptFailure;
|
return error.BlockingInterceptFailure;
|
||||||
@@ -265,23 +273,19 @@ pub fn request(self: *Client, req: Request) !void {
|
|||||||
|
|
||||||
switch (transfer._intercept_state) {
|
switch (transfer._intercept_state) {
|
||||||
.pending => continue, // keep waiting
|
.pending => continue, // keep waiting
|
||||||
.@"continue" => return self.process(transfer),
|
.@"continue" => return true,
|
||||||
.abort => {
|
.abort => |err| {
|
||||||
transfer.abort();
|
transfer.abort(err);
|
||||||
return;
|
return false;
|
||||||
},
|
},
|
||||||
.fulfilled => {
|
.fulfilled => {
|
||||||
// callbacks already called, just need to cleanups
|
// callbacks already called, just need to cleanups
|
||||||
transfer.deinit();
|
transfer.deinit();
|
||||||
return;
|
return false;
|
||||||
},
|
},
|
||||||
.not_intercepted => unreachable,
|
.not_intercepted => unreachable,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cdp_client.blocking_read_end(ctx) == false) {
|
|
||||||
return error.BlockingInterceptFailure;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Above, request will not process if there's an interception request. In such
|
// Above, request will not process if there's an interception request. In such
|
||||||
@@ -303,10 +307,10 @@ pub fn continueTransfer(self: *Client, transfer: *Transfer) !void {
|
|||||||
}
|
}
|
||||||
self.intercepted -= 1;
|
self.intercepted -= 1;
|
||||||
|
|
||||||
transfer._intercept_state = .@"continue";
|
|
||||||
if (!transfer.req.blocking) {
|
if (!transfer.req.blocking) {
|
||||||
return self.process(transfer);
|
return self.process(transfer);
|
||||||
}
|
}
|
||||||
|
transfer._intercept_state = .@"continue";
|
||||||
}
|
}
|
||||||
|
|
||||||
// For an intercepted request
|
// For an intercepted request
|
||||||
@@ -317,10 +321,10 @@ pub fn abortTransfer(self: *Client, transfer: *Transfer) void {
|
|||||||
}
|
}
|
||||||
self.intercepted -= 1;
|
self.intercepted -= 1;
|
||||||
|
|
||||||
transfer._intercept_state = .abort;
|
|
||||||
if (!transfer.req.blocking) {
|
if (!transfer.req.blocking) {
|
||||||
transfer.abort();
|
transfer.abort(error.Abort);
|
||||||
}
|
}
|
||||||
|
transfer._intercept_state = .{ .abort = error.Abort };
|
||||||
}
|
}
|
||||||
|
|
||||||
// For an intercepted request
|
// For an intercepted request
|
||||||
@@ -331,11 +335,11 @@ pub fn fulfillTransfer(self: *Client, transfer: *Transfer, status: u16, headers:
|
|||||||
}
|
}
|
||||||
self.intercepted -= 1;
|
self.intercepted -= 1;
|
||||||
|
|
||||||
transfer._intercept_state = .fulfilled;
|
|
||||||
try transfer.fulfill(status, headers, body);
|
try transfer.fulfill(status, headers, body);
|
||||||
if (!transfer.req.blocking) {
|
if (!transfer.req.blocking) {
|
||||||
transfer.deinit();
|
transfer.deinit();
|
||||||
}
|
}
|
||||||
|
transfer._intercept_state = .fulfilled;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn nextReqId(self: *Client) usize {
|
pub fn nextReqId(self: *Client) usize {
|
||||||
@@ -560,18 +564,22 @@ fn processMessages(self: *Client) !bool {
|
|||||||
var wait_for_interception = false;
|
var wait_for_interception = false;
|
||||||
notification.dispatch(.http_request_auth_required, &.{ .transfer = transfer, .wait_for_interception = &wait_for_interception });
|
notification.dispatch(.http_request_auth_required, &.{ .transfer = transfer, .wait_for_interception = &wait_for_interception });
|
||||||
if (wait_for_interception) {
|
if (wait_for_interception) {
|
||||||
// the request is put on hold to be intercepted.
|
|
||||||
// In this case we ignore callbacks for now.
|
|
||||||
// Note: we don't deinit transfer on purpose: we want to keep
|
|
||||||
// using it for the following request.
|
|
||||||
self.intercepted += 1;
|
self.intercepted += 1;
|
||||||
if (comptime IS_DEBUG) {
|
if (comptime IS_DEBUG) {
|
||||||
log.debug(.http, "wait for auth interception", .{ .intercepted = self.intercepted });
|
log.debug(.http, "wait for auth interception", .{ .intercepted = self.intercepted });
|
||||||
}
|
}
|
||||||
transfer._intercept_state = .pending;
|
transfer._intercept_state = .pending;
|
||||||
|
if (!transfer.req.blocking) {
|
||||||
|
// the request is put on hold to be intercepted.
|
||||||
|
// In this case we ignore callbacks for now.
|
||||||
|
// Note: we don't deinit transfer on purpose: we want to keep
|
||||||
|
// using it for the following request
|
||||||
self.endTransfer(transfer);
|
self.endTransfer(transfer);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_ = try self.waitForInterceptedResponse(transfer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -856,11 +864,11 @@ pub const Transfer = struct {
|
|||||||
_node: std.DoublyLinkedList.Node = .{},
|
_node: std.DoublyLinkedList.Node = .{},
|
||||||
_intercept_state: InterceptState = .not_intercepted,
|
_intercept_state: InterceptState = .not_intercepted,
|
||||||
|
|
||||||
const InterceptState = enum {
|
const InterceptState = union(enum) {
|
||||||
not_intercepted,
|
not_intercepted,
|
||||||
pending,
|
pending,
|
||||||
@"continue",
|
@"continue",
|
||||||
abort,
|
abort: anyerror,
|
||||||
fulfilled,
|
fulfilled,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -952,8 +960,8 @@ pub const Transfer = struct {
|
|||||||
self.req.headers = new_headers;
|
self.req.headers = new_headers;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn abort(self: *Transfer) void {
|
pub fn abort(self: *Transfer, err: anyerror) void {
|
||||||
self.client.requestFailed(self, error.Abort);
|
self.client.requestFailed(self, err);
|
||||||
if (self._handle != null) {
|
if (self._handle != null) {
|
||||||
self.client.endTransfer(self);
|
self.client.endTransfer(self);
|
||||||
}
|
}
|
||||||
@@ -978,8 +986,11 @@ pub const Transfer = struct {
|
|||||||
log.debug(.http, "abort auth transfer", .{ .intercepted = self.client.intercepted });
|
log.debug(.http, "abort auth transfer", .{ .intercepted = self.client.intercepted });
|
||||||
}
|
}
|
||||||
self.client.intercepted -= 1;
|
self.client.intercepted -= 1;
|
||||||
self.client.requestFailed(self, error.AbortAuthChallenge);
|
if (!self.req.blocking) {
|
||||||
self.deinit();
|
self.abort(error.AbortAuthChallenge);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self._intercept_state = .{ .abort = error.AbortAuthChallenge };
|
||||||
}
|
}
|
||||||
|
|
||||||
// redirectionCookies manages cookies during redirections handled by Curl.
|
// redirectionCookies manages cookies during redirections handled by Curl.
|
||||||
|
|||||||
Reference in New Issue
Block a user