diff --git a/src/browser/HttpClient.zig b/src/browser/HttpClient.zig index 8c7ba780..357c4ae9 100644 --- a/src/browser/HttpClient.zig +++ b/src/browser/HttpClient.zig @@ -44,6 +44,7 @@ pub const HeaderIterator = http.HeaderIterator; pub const CacheLayer = @import("../network/layer/CacheLayer.zig"); pub const RobotsLayer = @import("../network/layer/RobotsLayer.zig"); +pub const WebBotAuthLayer = @import("../network/layer/WebBotAuthLayer.zig"); pub const PerformStatus = enum { cdp_socket, normal }; @@ -593,34 +594,6 @@ pub const Layer = struct { } }; -// pub const WebBotAuthLayer = struct { -// next: Layer = undefined, -// allocator: std.mem.Allocator, -// // null when web_bot_auth is not configured -// auth: ?*WebBotAuth, - -// pub fn deinit(self: *WebBotAuthLayer) void { -// if (self.auth) |wba| wba.deinit(self.allocator); -// } - -// pub fn layer(self: *WebBotAuthLayer) Layer { -// return .{ -// .ptr = self, -// .vtable = &.{ .request = _request }, -// }; -// } - -// fn _request(ptr: *anyopaque, ctx: Context, req: Request) anyerror!void { -// const self: *WebBotAuthLayer = @ptrCast(@alignCast(ptr)); -// var our_req = req; -// if (self.auth) |auth| { -// const authority = URL.getHost(req.url); -// try auth.signRequest(ctx.arena, &our_req.headers, authority); -// } -// return self.next.request(ctx, our_req); -// } -// }; - pub fn LayerStack(comptime layer_types: anytype) type { return struct { ptrs: [layer_types.len]*anyopaque, @@ -669,8 +642,7 @@ pub fn LayerStack(comptime layer_types: anytype) type { }; } -// pub const Layers = LayerStack(.{ RobotsLayer, WebBotAuthLayer, CacheLayer }); -pub const Layers = LayerStack(.{ RobotsLayer, CacheLayer }); +pub const Layers = LayerStack(.{ RobotsLayer, WebBotAuthLayer, CacheLayer }); const Client = @This(); diff --git a/src/network/layer/WebBotAuthLayer.zig b/src/network/layer/WebBotAuthLayer.zig index e69de29b..5b23656e 100644 --- a/src/network/layer/WebBotAuthLayer.zig +++ b/src/network/layer/WebBotAuthLayer.zig @@ -0,0 +1,59 @@ +// Copyright (C) 2023-2026 Lightpanda (Selecy SAS) +// +// Francis Bouvier +// Pierre Tachoire +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +const std = @import("std"); +const log = @import("../../log.zig"); + +const URL = @import("../../browser/URL.zig"); +const WebBotAuth = @import("../WebBotAuth.zig"); +const Context = @import("../../browser/HttpClient.zig").Context; +const Request = @import("../../browser/HttpClient.zig").Request; +const Layer = @import("../../browser/HttpClient.zig").Layer; + +const WebBotAuthLayer = @This(); + +next: Layer = undefined, +auth: ?*WebBotAuth, + +pub fn layer(self: *WebBotAuthLayer) Layer { + return .{ + .ptr = self, + .vtable = &.{ .request = request }, + }; +} + +pub fn deinit(self: *WebBotAuthLayer, allocator: std.mem.Allocator) void { + if (self.auth) |wba| wba.deinit(allocator); +} + +fn request(ptr: *anyopaque, ctx: Context, req: Request) anyerror!void { + const self: *WebBotAuthLayer = @ptrCast(@alignCast(ptr)); + + if (self.auth == null) { + return self.next.request(ctx, req); + } + + const arena = try ctx.network.app.arena_pool.acquire(.{ .debug = "WebBotAuthLayer" }); + defer ctx.network.app.arena_pool.release(arena); + + var our_req = req; + const authority = URL.getHost(req.url); + try self.auth.?.signRequest(arena, &our_req.headers, authority); + + return self.next.request(ctx, our_req); +}