Skip to content

Commit 910c715

Browse files
committed
First version of headers, no cookies yet
1 parent bac639a commit 910c715

File tree

7 files changed

+93
-50
lines changed

7 files changed

+93
-50
lines changed

src/browser/ScriptManager.zig

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ deferreds: OrderList,
5757

5858
shutdown: bool = false,
5959

60-
6160
client: *HttpClient,
6261
allocator: Allocator,
6362
buffer_pool: BufferPool,
@@ -230,6 +229,7 @@ pub fn addFromElement(self: *ScriptManager, element: *parser.Element) !void {
230229
.url = remote_url.?,
231230
.ctx = pending_script,
232231
.method = .GET,
232+
.headers = try HttpClient.Headers.init(),
233233
.cookie = page.requestCookie(.{}),
234234
.start_callback = if (log.enabled(.http, .debug)) startCallback else null,
235235
.header_done_callback = headerCallback,
@@ -293,6 +293,7 @@ pub fn blockingGet(self: *ScriptManager, url: [:0]const u8) !BlockingResult {
293293
try client.blockingRequest(.{
294294
.url = url,
295295
.method = .GET,
296+
.headers = try HttpClient.Headers.init(),
296297
.ctx = &blocking,
297298
.cookie = self.page.requestCookie(.{}),
298299
.start_callback = if (log.enabled(.http, .debug)) Blocking.startCallback else null,

src/browser/page.zig

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -433,12 +433,15 @@ pub const Page = struct {
433433
const owned_url = try self.arena.dupeZ(u8, request_url);
434434
self.url = try URL.parse(owned_url, null);
435435

436+
var headers = try HttpClient.Headers.init();
437+
if (opts.header) |hdr| try headers.add(hdr);
438+
436439
self.http_client.request(.{
437440
.ctx = self,
438441
.url = owned_url,
439442
.method = opts.method,
443+
.headers = headers,
440444
.body = opts.body,
441-
.header = opts.header,
442445
.cookie = self.requestCookie(.{ .is_navigation = true }),
443446
.header_done_callback = pageHeaderDoneCallback,
444447
.data_callback = pageDataCallback,

src/browser/xhr/xhr.zig

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -370,10 +370,16 @@ pub const XMLHttpRequest = struct {
370370
}
371371
}
372372

373+
var headers = try HttpClient.Headers.init();
374+
for (self.headers.items) |hdr| {
375+
try headers.add(hdr);
376+
}
377+
373378
try page.http_client.request(.{
374379
.ctx = self,
375380
.url = self.url.?,
376381
.method = self.method,
382+
.headers = headers,
377383
.body = self.request_body,
378384
.cookie = page.requestCookie(.{}),
379385
.start_callback = httpStartCallback,
@@ -387,11 +393,6 @@ pub const XMLHttpRequest = struct {
387393

388394
fn httpStartCallback(transfer: *HttpClient.Transfer) !void {
389395
const self: *XMLHttpRequest = @alignCast(@ptrCast(transfer.ctx));
390-
391-
for (self.headers.items) |hdr| {
392-
try transfer.addHeader(hdr);
393-
}
394-
395396
log.debug(.http, "request start", .{ .method = self.method, .url = self.url, .source = "xhr" });
396397
self.transfer = transfer;
397398
}

src/cdp/domains/fetch.zig

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -149,11 +149,7 @@ pub fn requestPaused(arena: Allocator, bc: anytype, intercept: *const Notificati
149149
const request_fragment = try @import("network.zig").urlToString(arena, &full_request_url, .{
150150
.fragment = true,
151151
});
152-
const headers: std.StringArrayHashMapUnmanaged([]const u8) = .empty;
153-
// try headers.ensureTotalCapacity(arena, request.headers.items.len);
154-
// for (request.headers.items) |header| {
155-
// headers.putAssumeCapacity(header.name, header.value);
156-
// }
152+
const headers = try intercept.request.headers.asHashMap(arena);
157153
// End of duped code
158154

159155
try cdp.sendEvent("Fetch.requestPaused", .{

src/cdp/domains/network.zig

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -263,12 +263,7 @@ pub fn httpRequestStart(arena: Allocator, bc: anytype, data: *const Notification
263263
.fragment = true, // TODO since path is false, this likely does not work as intended
264264
});
265265

266-
// @newhttp
267-
const headers: std.StringArrayHashMapUnmanaged([]const u8) = .empty;
268-
// try headers.ensureTotalCapacity(arena, request.headers.items.len);
269-
// for (request.headers.items) |header| {
270-
// headers.putAssumeCapacity(header.name, header.value);
271-
// }
266+
const headers = try data.request.headers.asHashMap(arena);
272267

273268
// We're missing a bunch of fields, but, for now, this seems like enough
274269
try cdp.sendEvent("Network.requestWillBeSent", .{

src/http/Client.zig

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ const std = @import("std");
2020
const log = @import("../log.zig");
2121
const builtin = @import("builtin");
2222
const Http = @import("Http.zig");
23+
pub const Headers = Http.Headers;
2324
const Notification = @import("../notification.zig").Notification;
2425

2526
const c = Http.c;
@@ -260,7 +261,8 @@ fn makeRequest(self: *Client, handle: *Handle, req: Request) !void {
260261
return;
261262
};
262263

263-
const header_list = blk: {
264+
var header_list = req.headers;
265+
{
264266
errdefer self.handles.release(handle);
265267
try conn.setMethod(req.method);
266268
try conn.setURL(req.url);
@@ -269,31 +271,23 @@ fn makeRequest(self: *Client, handle: *Handle, req: Request) !void {
269271
try conn.setBody(b);
270272
}
271273

272-
var header_list = conn.commonHeaders();
273-
errdefer c.curl_slist_free_all(header_list);
274-
275-
if (req.header) |hdr| {
276-
header_list = c.curl_slist_append(header_list, hdr);
277-
}
278-
279-
{
280-
const aa = self.arena.allocator();
281-
var arr: std.ArrayListUnmanaged(u8) = .{};
282-
try req.cookie.forRequest(&uri, arr.writer(aa));
283-
284-
if (arr.items.len > 0) {
285-
try arr.append(aa, 0); //null terminate
274+
// { // TODO move up to `fn request()`
275+
// const aa = self.arena.allocator();
276+
// var arr: std.ArrayListUnmanaged(u8) = .{};
277+
// try req.cookie.forRequest(&uri, arr.writer(aa));
286278

287-
// copies the value
288-
header_list = c.curl_slist_append(header_list, @ptrCast(arr.items.ptr));
289-
defer _ = self.arena.reset(.{ .retain_with_limit = 2048 });
290-
}
291-
}
279+
// if (arr.items.len > 0) {
280+
// try arr.append(aa, 0); //null terminate
292281

293-
try errorCheck(c.curl_easy_setopt(easy, c.CURLOPT_HTTPHEADER, header_list));
282+
// // copies the value
283+
// header_list = c.curl_slist_append(header_list, @ptrCast(arr.items.ptr));
284+
// defer _ = self.arena.reset(.{ .retain_with_limit = 2048 });
285+
// }
286+
// }
294287

295-
break :blk header_list;
296-
};
288+
try conn.secretHeaders(&header_list); // Add headers that must be hidden from intercepts
289+
try errorCheck(c.curl_easy_setopt(easy, c.CURLOPT_HTTPHEADER, header_list.headers));
290+
}
297291

298292
{
299293
errdefer self.handles.release(handle);
@@ -305,7 +299,7 @@ fn makeRequest(self: *Client, handle: *Handle, req: Request) !void {
305299
.req = req,
306300
.ctx = req.ctx,
307301
.handle = handle,
308-
._request_header_list = header_list,
302+
._request_header_list = header_list.headers,
309303
};
310304
errdefer self.transfer_pool.destroy(transfer);
311305

@@ -495,8 +489,8 @@ pub const Request = struct {
495489
id: ?u64 = null,
496490
method: Method,
497491
url: [:0]const u8,
492+
headers: Headers,
498493
body: ?[]const u8 = null,
499-
header: ?[:0]const u8 = null,
500494
cookie: RequestCookie,
501495

502496
// arbitrary data that can be associated with this request

src/http/Http.zig

Lines changed: 60 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -185,20 +185,20 @@ pub const Connection = struct {
185185
try errorCheck(c.curl_easy_setopt(easy, c.CURLOPT_POSTFIELDS, body.ptr));
186186
}
187187

188-
pub fn commonHeaders(self: *const Connection) *c.curl_slist {
189-
var header_list = c.curl_slist_append(null, "User-Agent: Lightpanda/1.0");
188+
// These are headers that may not be send to the users for inteception.
189+
pub fn secretHeaders(self: *const Connection, headers: *Headers) !void {
190190
if (self.opts.proxy_bearer_token) |hdr| {
191-
header_list = c.curl_slist_append(header_list, hdr);
191+
try headers.add(hdr);
192192
}
193-
return header_list;
194193
}
195194

196195
pub fn request(self: *const Connection) !u16 {
197196
const easy = self.easy;
198197

199-
const header_list = self.commonHeaders();
200-
defer c.curl_slist_free_all(header_list);
201-
try errorCheck(c.curl_easy_setopt(easy, c.CURLOPT_HTTPHEADER, header_list));
198+
const header_list = try Headers.init();
199+
defer header_list.deinit();
200+
try self.secretHeaders(&header_list);
201+
try errorCheck(c.curl_easy_setopt(easy, c.CURLOPT_HTTPHEADER, header_list.headers));
202202

203203
try errorCheck(c.curl_easy_perform(easy));
204204
var http_code: c_long = undefined;
@@ -210,6 +210,59 @@ pub const Connection = struct {
210210
}
211211
};
212212

213+
pub const Headers = struct {
214+
headers: *c.curl_slist,
215+
216+
pub fn init() !Headers {
217+
const header_list = c.curl_slist_append(null, "User-Agent: Lightpanda/1.0");
218+
if (header_list == null) return error.OutOfMemory;
219+
return .{ .headers = header_list };
220+
}
221+
222+
pub fn deinit(self: *Headers) void {
223+
c.curl_slist_free_all(self.headers);
224+
}
225+
226+
pub fn add(self: *Headers, header: [*c]const u8) !void {
227+
const updated_headers = c.curl_slist_append(self.headers, header);
228+
if (updated_headers == null) return error.OutOfMemory;
229+
self.headers = updated_headers;
230+
}
231+
232+
pub fn asHashMap(self: *const Headers, allocator: Allocator) !std.StringArrayHashMapUnmanaged([]const u8) {
233+
var list: std.StringArrayHashMapUnmanaged([]const u8) = .empty;
234+
try list.ensureTotalCapacity(allocator, self.count());
235+
236+
var current: [*c]c.curl_slist = self.headers;
237+
while (current) |node| {
238+
const str = std.mem.span(@as([*:0]const u8, @ptrCast(node.*.data)));
239+
const header = parseHeader(str) orelse return error.InvalidHeader;
240+
list.putAssumeCapacity(header.name, header.value);
241+
current = node.*.next;
242+
}
243+
return list;
244+
}
245+
246+
fn parseHeader(header_str: []const u8) ?struct { name: []const u8, value: []const u8 } {
247+
const colon_pos = std.mem.indexOf(u8, header_str, ":") orelse return null;
248+
249+
const name = std.mem.trim(u8, header_str[0..colon_pos], " \t");
250+
const value = std.mem.trim(u8, header_str[colon_pos + 1 ..], " \t");
251+
252+
return .{ .name = name, .value = value };
253+
}
254+
255+
pub fn count(self: *const Headers) usize {
256+
var current: [*c]c.curl_slist = self.headers;
257+
var num: usize = 0;
258+
while (current) |node| {
259+
num += 1;
260+
current = node.*.next;
261+
}
262+
return num;
263+
}
264+
};
265+
213266
pub fn errorCheck(code: c.CURLcode) errors.Error!void {
214267
if (code == c.CURLE_OK) {
215268
return;

0 commit comments

Comments
 (0)