1818
1919const std = @import ("std" );
2020const Allocator = std .mem .Allocator ;
21- const Notification = @import ( "../../notification.zig" ). Notification ;
21+
2222const log = @import ("../../log.zig" );
23+ const network = @import ("network.zig" );
24+
2325const Method = @import ("../../http/Client.zig" ).Method ;
2426const Transfer = @import ("../../http/Client.zig" ).Transfer ;
27+ const Notification = @import ("../../notification.zig" ).Notification ;
2528
2629pub fn processMessage (cmd : anytype ) ! void {
2730 const action = std .meta .stringToEnum (enum {
@@ -41,22 +44,38 @@ pub fn processMessage(cmd: anytype) !void {
4144
4245// Stored in CDP
4346pub const InterceptState = struct {
44- const Self = @This ();
45- waiting : std .AutoArrayHashMap (u64 , * Transfer ),
47+ allocator : Allocator ,
48+ waiting : std .AutoArrayHashMapUnmanaged (u64 , * Transfer ),
4649
4750 pub fn init (allocator : Allocator ) ! InterceptState {
4851 return .{
49- .waiting = std .AutoArrayHashMap (u64 , * Transfer ).init (allocator ),
52+ .waiting = .empty ,
53+ .allocator = allocator ,
5054 };
5155 }
5256
53- pub fn deinit (self : * Self ) void {
54- self .waiting .deinit ();
57+ pub fn empty (self : * const InterceptState ) bool {
58+ return self .waiting .count () == 0 ;
59+ }
60+
61+ pub fn put (self : * InterceptState , transfer : * Transfer ) ! void {
62+ return self .waiting .put (self .allocator , transfer .id , transfer );
63+ }
64+
65+ pub fn remove (self : * InterceptState , id : u64 ) ? * Transfer {
66+ const entry = self .waiting .fetchSwapRemove (id ) orelse return null ;
67+ return entry .value ;
68+ }
69+
70+ pub fn deinit (self : * InterceptState ) void {
71+ self .waiting .deinit (self .allocator );
5572 }
5673};
5774
5875const RequestPattern = struct {
59- urlPattern : []const u8 = "*" , // Wildcards ('*' -> zero or more, '?' -> exactly one) are allowed. Escape character is backslash. Omitting is equivalent to "*".
76+ // Wildcards ('*' -> zero or more, '?' -> exactly one) are allowed.
77+ // Escape character is backslash. Omitting is equivalent to "*".
78+ urlPattern : []const u8 = "*" ,
6079 resourceType : ? ResourceType = null ,
6180 requestStage : RequestStage = .Request ,
6281};
@@ -115,60 +134,46 @@ fn disable(cmd: anytype) !void {
115134
116135fn enable (cmd : anytype ) ! void {
117136 const params = (try cmd .params (EnableParam )) orelse EnableParam {};
118- if (params .patterns .len != 0 ) log .warn (.cdp , "Fetch.enable No patterns yet" , .{});
119- if (params .handleAuthRequests ) log .warn (.cdp , "Fetch.enable No auth yet" , .{});
137+ if (params .patterns .len != 0 ) {
138+ log .warn (.cdp , "not implemented" , .{ .feature = "Fetch.enable No patterns yet" });
139+ }
140+ if (params .handleAuthRequests ) {
141+ log .warn (.cdp , "not implemented" , .{ .feature = "Fetch.enable No auth yet" });
142+ }
120143
121144 const bc = cmd .browser_context orelse return error .BrowserContextNotLoaded ;
122145 try bc .fetchEnable ();
123146
124147 return cmd .sendResult (null , .{});
125148}
126149
127- pub fn requestPaused (arena : Allocator , bc : anytype , intercept : * const Notification.RequestIntercept ) ! void {
150+ pub fn requestIntercept (arena : Allocator , bc : anytype , intercept : * const Notification.RequestIntercept ) ! void {
128151 var cdp = bc .cdp ;
129152
130153 // unreachable because we _have_ to have a page.
131154 const session_id = bc .session_id orelse unreachable ;
132155 const target_id = bc .target_id orelse unreachable ;
156+ const page = bc .session .currentPage () orelse unreachable ;
133157
134158 // We keep it around to wait for modifications to the request.
135159 // NOTE: we assume whomever created the request created it with a lifetime of the Page.
136160 // TODO: What to do when receiving replies for a previous page's requests?
137161
138162 const transfer = intercept .transfer ;
139- try cdp .intercept_state .waiting .put (transfer .id , transfer );
140-
141- // NOTE: .request data preparation is duped from network.zig
142- const full_request_url = transfer .uri ;
143- const request_url = try @import ("network.zig" ).urlToString (arena , & full_request_url , .{
144- .scheme = true ,
145- .authentication = true ,
146- .authority = true ,
147- .path = true ,
148- .query = true ,
149- });
150- const request_fragment = try @import ("network.zig" ).urlToString (arena , & full_request_url , .{
151- .fragment = true ,
152- });
153- const headers = try transfer .req .headers .asHashMap (arena );
154- // End of duped code
163+ try cdp .intercept_state .put (transfer );
155164
156165 try cdp .sendEvent ("Fetch.requestPaused" , .{
157166 .requestId = try std .fmt .allocPrint (arena , "INTERCEPT-{d}" , .{transfer .id }),
158- .request = .{
159- .url = request_url ,
160- .urlFragment = request_fragment ,
161- .method = @tagName (transfer .req .method ),
162- .hasPostData = transfer .req .body != null ,
163- .headers = std .json .ArrayHashMap ([]const u8 ){ .map = headers },
164- },
167+ .request = network .TransferAsRequestWriter .init (transfer ),
165168 .frameId = target_id ,
166169 .resourceType = ResourceType .Document , // TODO!
167170 .networkId = try std .fmt .allocPrint (arena , "REQ-{d}" , .{transfer .id }),
168171 }, .{ .session_id = session_id });
169172
170173 // Await either continueRequest, failRequest or fulfillRequest
174+
171175 intercept .wait_for_interception .* = true ;
176+ page .request_intercepted = true ;
172177}
173178
174179const HeaderEntry = struct {
@@ -186,46 +191,67 @@ fn continueRequest(cmd: anytype) !void {
186191 headers : ? []const HeaderEntry = null ,
187192 interceptResponse : bool = false ,
188193 })) orelse return error .InvalidParams ;
189- if (params .postData != null or params .headers != null or params .interceptResponse ) return error .NotYetImplementedParams ;
190194
195+ if (params .postData != null or params .headers != null or params .interceptResponse ) {
196+ return error .NotYetImplementedParams ;
197+ }
198+
199+ const page = bc .session .currentPage () orelse return error .PageNotLoaded ;
200+
201+ var intercept_state = & bc .cdp .intercept_state ;
191202 const request_id = try idFromRequestId (params .requestId );
192- const entry = bc .cdp .intercept_state .waiting .fetchSwapRemove (request_id ) orelse return error .RequestNotFound ;
193- const transfer = entry .value ;
203+ const transfer = intercept_state .remove (request_id ) orelse return error .RequestNotFound ;
194204
195205 // Update the request with the new parameters
196206 if (params .url ) | url | {
197- // The request url must be modified in a way that's not observable by page. So page.url is not updated.
198- try transfer .updateURL (try bc .cdp .browser .page_arena .allocator ().dupeZ (u8 , url ));
207+ // The request url must be modified in a way that's not observable by page.
208+ // So page.url is not updated.
209+ try transfer .updateURL (try page .arena .dupeZ (u8 , url ));
199210 }
200211 if (params .method ) | method | {
201212 transfer .req .method = std .meta .stringToEnum (Method , method ) orelse return error .InvalidParams ;
202213 }
203214
204- log .info (.cdp , "Request continued by intercept" , .{ .id = params .requestId });
215+ log .info (.cdp , "Request continued by intercept" , .{
216+ .id = params .requestId ,
217+ .url = transfer .uri ,
218+ });
205219 try bc .cdp .browser .http_client .process (transfer );
206220
221+ if (intercept_state .empty ()) {
222+ page .request_intercepted = false ;
223+ }
224+
207225 return cmd .sendResult (null , .{});
208226}
209227
210228fn failRequest (cmd : anytype ) ! void {
211229 const bc = cmd .browser_context orelse return error .BrowserContextNotLoaded ;
212- var state = & bc .cdp .intercept_state ;
213230 const params = (try cmd .params (struct {
214231 requestId : []const u8 , // "INTERCEPT-{d}"
215232 errorReason : ErrorReason ,
216233 })) orelse return error .InvalidParams ;
217234
235+ const page = bc .session .currentPage () orelse return error .PageNotLoaded ;
236+
237+ var intercept_state = & bc .cdp .intercept_state ;
218238 const request_id = try idFromRequestId (params .requestId );
219- const entry = state .waiting .fetchSwapRemove (request_id ) orelse return error .RequestNotFound ;
220- // entry.value is the transfer
221- entry .value .abort ();
239+
240+ const transfer = intercept_state .remove (request_id ) orelse return error .RequestNotFound ;
241+ transfer .abort ();
242+
243+ if (intercept_state .empty ()) {
244+ page .request_intercepted = false ;
245+ }
222246
223247 log .info (.cdp , "Request aborted by intercept" , .{ .reason = params .errorReason });
224248 return cmd .sendResult (null , .{});
225249}
226250
227251// Get u64 from requestId which is formatted as: "INTERCEPT-{d}"
228252fn idFromRequestId (request_id : []const u8 ) ! u64 {
229- if (! std .mem .startsWith (u8 , request_id , "INTERCEPT-" )) return error .InvalidParams ;
253+ if (! std .mem .startsWith (u8 , request_id , "INTERCEPT-" )) {
254+ return error .InvalidParams ;
255+ }
230256 return std .fmt .parseInt (u64 , request_id [10.. ], 10 ) catch return error .InvalidParams ;
231257}
0 commit comments