3# This is a combination of 3 commits.

intercept continue and abort

feedback

First version of headers, no cookies yet
This commit is contained in:
sjorsdonkers
2025-08-12 13:49:20 +02:00
parent bed320204d
commit 03694b54f0
10 changed files with 357 additions and 64 deletions

View File

@@ -20,6 +20,8 @@ const std = @import("std");
const log = @import("../log.zig");
const builtin = @import("builtin");
const Http = @import("Http.zig");
pub const Headers = Http.Headers;
const Notification = @import("../notification.zig").Notification;
const c = Http.c;
@@ -57,6 +59,9 @@ multi: *c.CURLM,
// of easys.
handles: Handles,
// Use to generate the next request ID
next_request_id: u64 = 0,
// When handles has no more available easys, requests get queued.
queue: RequestQueue,
@@ -74,6 +79,9 @@ transfer_pool: std.heap.MemoryPool(Transfer),
// see ScriptManager.blockingGet
blocking: Handle,
// To notify registered subscribers of events, the browser sets/nulls this for us.
notification: ?*Notification = null,
// The only place this is meant to be used is in `makeRequest` BEFORE `perform`
// is called. It is used to generate our Cookie header. It can be used for other
// purposes, but keep in mind that, while single-threaded, calls like makeRequest
@@ -184,12 +192,26 @@ pub fn tick(self: *Client, timeout_ms: usize) !void {
}
pub fn request(self: *Client, req: Request) !void {
var req_copy = req; // We need it mutable
if (req_copy.id == null) { // If the ID has already been set that means the request was previously intercepted
req_copy.id = self.next_request_id;
self.next_request_id += 1;
if (self.notification) |notification| {
notification.dispatch(.http_request_start, &.{ .request = &req_copy });
var wait_for_interception = false;
notification.dispatch(.http_request_intercept, &.{ .request = &req_copy, .wait_for_interception = &wait_for_interception });
if (wait_for_interception) return; // The user is send an invitation to intercept this request.
}
}
if (self.handles.getFreeHandle()) |handle| {
return self.makeRequest(handle, req);
return self.makeRequest(handle, req_copy);
}
const node = try self.queue_node_pool.create();
node.data = req;
node.data = req_copy;
self.queue.append(node);
}
@@ -239,7 +261,8 @@ fn makeRequest(self: *Client, handle: *Handle, req: Request) !void {
return;
};
const header_list = blk: {
var header_list = req.headers;
{
errdefer self.handles.release(handle);
try conn.setMethod(req.method);
try conn.setURL(req.url);
@@ -248,31 +271,23 @@ fn makeRequest(self: *Client, handle: *Handle, req: Request) !void {
try conn.setBody(b);
}
var header_list = conn.commonHeaders();
errdefer c.curl_slist_free_all(header_list);
// { // TODO move up to `fn request()`
// const aa = self.arena.allocator();
// var arr: std.ArrayListUnmanaged(u8) = .{};
// try req.cookie.forRequest(&uri, arr.writer(aa));
if (req.header) |hdr| {
header_list = c.curl_slist_append(header_list, hdr);
}
// if (arr.items.len > 0) {
// try arr.append(aa, 0); //null terminate
{
const aa = self.arena.allocator();
var arr: std.ArrayListUnmanaged(u8) = .{};
try req.cookie.forRequest(&uri, arr.writer(aa));
// // copies the value
// header_list = c.curl_slist_append(header_list, @ptrCast(arr.items.ptr));
// defer _ = self.arena.reset(.{ .retain_with_limit = 2048 });
// }
// }
if (arr.items.len > 0) {
try arr.append(aa, 0); //null terminate
// copies the value
header_list = c.curl_slist_append(header_list, @ptrCast(arr.items.ptr));
defer _ = self.arena.reset(.{ .retain_with_limit = 2048 });
}
}
try errorCheck(c.curl_easy_setopt(easy, c.CURLOPT_HTTPHEADER, header_list));
break :blk header_list;
};
try conn.secretHeaders(&header_list); // Add headers that must be hidden from intercepts
try errorCheck(c.curl_easy_setopt(easy, c.CURLOPT_HTTPHEADER, header_list.headers));
}
{
errdefer self.handles.release(handle);
@@ -284,7 +299,7 @@ fn makeRequest(self: *Client, handle: *Handle, req: Request) !void {
.req = req,
.ctx = req.ctx,
.handle = handle,
._request_header_list = header_list,
._request_header_list = header_list.headers,
};
errdefer self.transfer_pool.destroy(transfer);
@@ -471,10 +486,11 @@ pub const RequestCookie = struct {
};
pub const Request = struct {
id: ?u64 = null,
method: Method,
url: [:0]const u8,
headers: Headers,
body: ?[]const u8 = null,
header: ?[:0]const u8 = null,
cookie: RequestCookie,
// arbitrary data that can be associated with this request