18
18
19
19
const std = @import ("std" );
20
20
const Notification = @import ("../../notification.zig" ).Notification ;
21
+ const log = @import ("../../log.zig" );
21
22
22
23
const Allocator = std .mem .Allocator ;
23
24
@@ -26,12 +27,14 @@ pub fn processMessage(cmd: anytype) !void {
26
27
enable ,
27
28
disable ,
28
29
setCacheDisabled ,
30
+ setExtraHTTPHeaders ,
29
31
}, cmd .input .action ) orelse return error .UnknownMethod ;
30
32
31
33
switch (action ) {
32
34
.enable = > return enable (cmd ),
33
35
.disable = > return disable (cmd ),
34
36
.setCacheDisabled = > return cmd .sendResult (null , .{}),
37
+ .setExtraHTTPHeaders = > return setExtraHTTPHeaders (cmd ),
35
38
}
36
39
}
37
40
@@ -47,6 +50,27 @@ fn disable(cmd: anytype) !void {
47
50
return cmd .sendResult (null , .{});
48
51
}
49
52
53
+ fn setExtraHTTPHeaders (cmd : anytype ) ! void {
54
+ const params = (try cmd .params (struct {
55
+ headers : std .json .ArrayHashMap ([]const u8 ),
56
+ })) orelse return error .InvalidParams ;
57
+
58
+ const bc = cmd .browser_context orelse return error .BrowserContextNotLoaded ;
59
+
60
+ // Copy the headers onto the browser context arena
61
+ const arena = bc .arena ;
62
+ const extra_headers = & bc .cdp .extra_headers ;
63
+
64
+ extra_headers .clearRetainingCapacity ();
65
+ try extra_headers .ensureTotalCapacity (arena , params .headers .map .count ());
66
+ var it = params .headers .map .iterator ();
67
+ while (it .next ()) | header | {
68
+ extra_headers .appendAssumeCapacity (.{ .name = try arena .dupe (u8 , header .key_ptr .* ), .value = try arena .dupe (u8 , header .value_ptr .* ) });
69
+ }
70
+
71
+ return cmd .sendResult (null , .{});
72
+ }
73
+
50
74
pub fn httpRequestStart (arena : Allocator , bc : anytype , request : * const Notification.RequestStart ) ! void {
51
75
// Isn't possible to do a network request within a Browser (which our
52
76
// notification is tied to), without a page.
@@ -59,6 +83,21 @@ pub fn httpRequestStart(arena: Allocator, bc: anytype, request: *const Notificat
59
83
const target_id = bc .target_id orelse unreachable ;
60
84
const page = bc .session .currentPage () orelse unreachable ;
61
85
86
+ // Modify request with extra CDP headers
87
+ const original_len = request .headers .items .len ;
88
+ try request .headers .ensureTotalCapacity (arena , original_len + cdp .extra_headers .items .len );
89
+ outer : for (cdp .extra_headers .items ) | extra | {
90
+ for (request .headers .items [0.. original_len ]) | * existing_header | {
91
+ if (std .mem .eql (u8 , existing_header .name , extra .name )) {
92
+ // If the header already exists, we overwrite it
93
+ log .debug (.cdp , "request header overwritten" , .{ .name = extra .name });
94
+ existing_header .value = extra .value ;
95
+ continue :outer ;
96
+ }
97
+ }
98
+ request .headers .appendAssumeCapacity (extra );
99
+ }
100
+
62
101
const document_url = try urlToString (arena , & page .url .uri , .{
63
102
.scheme = true ,
64
103
.authentication = true ,
@@ -80,8 +119,8 @@ pub fn httpRequestStart(arena: Allocator, bc: anytype, request: *const Notificat
80
119
});
81
120
82
121
var headers : std .StringArrayHashMapUnmanaged ([]const u8 ) = .empty ;
83
- try headers .ensureTotalCapacity (arena , request .headers .len );
84
- for (request .headers ) | header | {
122
+ try headers .ensureTotalCapacity (arena , request .headers .items . len );
123
+ for (request .headers . items ) | header | {
85
124
headers .putAssumeCapacity (header .name , header .value );
86
125
}
87
126
@@ -129,13 +168,13 @@ pub fn httpRequestComplete(arena: Allocator, bc: anytype, request: *const Notifi
129
168
// We're missing a bunch of fields, but, for now, this seems like enough
130
169
try cdp .sendEvent ("Network.responseReceived" , .{
131
170
.requestId = try std .fmt .allocPrint (arena , "REQ-{d}" , .{request .id }),
132
- .frameId = target_id ,
133
171
.loaderId = bc .loader_id ,
134
172
.response = .{
135
173
.url = url ,
136
174
.status = request .status ,
137
175
.headers = std .json .ArrayHashMap ([]const u8 ){ .map = headers },
138
176
},
177
+ .frameId = target_id ,
139
178
}, .{ .session_id = session_id });
140
179
}
141
180
@@ -144,3 +183,26 @@ fn urlToString(arena: Allocator, url: *const std.Uri, opts: std.Uri.WriteToStrea
144
183
try url .writeToStream (opts , buf .writer (arena ));
145
184
return buf .items ;
146
185
}
186
+
187
+ const testing = @import ("../testing.zig" );
188
+ test "cdp.network setExtraHTTPHeaders" {
189
+ var ctx = testing .context ();
190
+ defer ctx .deinit ();
191
+
192
+ // _ = try ctx.loadBrowserContext(.{ .id = "NID-A", .session_id = "NESI-A" });
193
+ try ctx .processMessage (.{ .id = 10 , .method = "Target.createTarget" , .params = .{ .url = "about/blank" } });
194
+
195
+ try ctx .processMessage (.{
196
+ .id = 3 ,
197
+ .method = "Network.setExtraHTTPHeaders" ,
198
+ .params = .{ .headers = .{ .foo = "bar" } },
199
+ });
200
+
201
+ try ctx .processMessage (.{
202
+ .id = 4 ,
203
+ .method = "Network.setExtraHTTPHeaders" ,
204
+ .params = .{ .headers = .{ .food = "bars" } },
205
+ });
206
+
207
+ try testing .expectEqual (ctx .cdp_ .? .browser_context .? .cdp .extra_headers .items .len , 1 );
208
+ }
0 commit comments