Skip to content

Commit 4bef1d8

Browse files
committed
support CDP proxy override
1 parent 5d9e283 commit 4bef1d8

File tree

4 files changed

+60
-15
lines changed

4 files changed

+60
-15
lines changed

src/cdp/cdp.zig

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -338,10 +338,7 @@ pub fn BrowserContext(comptime CDP_T: type) type {
338338
inspector: Inspector,
339339
isolated_world: ?IsolatedWorld,
340340

341-
// Used to restore the proxy after the CDP session ends. If CDP never over-wrote it, it won't restore it (the first null).
342-
// If the CDP is restoring it, but the original value was null, that's the 2nd null.
343-
// If you only have 1 null it would be ambiguous, does null mean it shouldn't be restored, or should it be restored to null?
344-
http_proxy_before: ??std.Uri = null,
341+
http_proxy_changed: bool = false,
345342

346343
const Self = @This();
347344

@@ -397,7 +394,13 @@ pub fn BrowserContext(comptime CDP_T: type) type {
397394
self.node_search_list.deinit();
398395
self.cdp.browser.notification.unregisterAll(self);
399396

400-
if (self.http_proxy_before) |prev_proxy| self.cdp.browser.http_client.http_proxy = prev_proxy;
397+
if (self.http_proxy_changed) {
398+
// has to be called after browser.closeSession, since it won't
399+
// work if there are active connections.
400+
self.cdp.browser.http_client.restoreOriginalProxy() catch |err| {
401+
log.warn(.http, "restoreOriginalProxy", .{ .err = err });
402+
};
403+
}
401404
}
402405

403406
pub fn reset(self: *Self) void {

src/cdp/domains/target.zig

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ fn getBrowserContexts(cmd: anytype) !void {
6868
fn createBrowserContext(cmd: anytype) !void {
6969
const params = try cmd.params(struct {
7070
disposeOnDetach: bool = false,
71-
proxyServer: ?[]const u8 = null,
71+
proxyServer: ?[:0]const u8 = null,
7272
proxyBypassList: ?[]const u8 = null,
7373
originsWithUniversalNetworkAccess: ?[]const []const u8 = null,
7474
});
@@ -84,9 +84,8 @@ fn createBrowserContext(cmd: anytype) !void {
8484
if (params) |p| {
8585
if (p.proxyServer) |proxy| {
8686
// For now the http client is not in the browser context so we assume there is just 1.
87-
bc.http_proxy_before = cmd.cdp.browser.http_client.http_proxy;
88-
const proxy_cp = try cmd.cdp.browser.http_client.allocator.dupe(u8, proxy);
89-
cmd.cdp.browser.http_client.http_proxy = try std.Uri.parse(proxy_cp);
87+
try cmd.cdp.browser.http_client.changeProxy(proxy);
88+
bc.http_proxy_changed = true;
9089
}
9190
}
9291

src/http/Client.zig

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,6 @@ allocator: Allocator,
7171
// request. These wil come and go with each request.
7272
transfer_pool: std.heap.MemoryPool(Transfer),
7373

74-
//@newhttp
75-
http_proxy: ?std.Uri = null,
76-
7774
// see ScriptManager.blockingGet
7875
blocking: Handle,
7976

@@ -87,6 +84,10 @@ blocking_active: if (builtin.mode == .Debug) bool else void = if (builtin.mode =
8784
// can result in makeRequest being re-called (from a doneCallback).
8885
arena: ArenaAllocator,
8986

87+
// only needed for CDP which can change the proxy and then restore it. When
88+
// restoring, this originally-configured value is what it goes to.
89+
http_proxy: ?[:0]const u8 = null,
90+
9091
const RequestQueue = std.DoublyLinkedList(Request);
9192

9293
pub fn init(allocator: Allocator, ca_blob: ?c.curl_blob, opts: Http.Opts) !*Client {
@@ -117,6 +118,7 @@ pub fn init(allocator: Allocator, ca_blob: ?c.curl_blob, opts: Http.Opts) !*Clie
117118
.handles = handles,
118119
.blocking = blocking,
119120
.allocator = allocator,
121+
.http_proxy = opts.http_proxy,
120122
.transfer_pool = transfer_pool,
121123
.queue_node_pool = queue_node_pool,
122124
.arena = ArenaAllocator.init(allocator),
@@ -208,6 +210,36 @@ pub fn blockingRequest(self: *Client, req: Request) !void {
208210
return self.makeRequest(&self.blocking, req);
209211
}
210212

213+
// Restrictive since it'll only work if there are no inflight requests. In some
214+
// cases, the libcurl documentation is clear that changing settings while a
215+
// connection is inflight is undefined. It doesn't say anything about CURLOPT_PROXY,
216+
// but better to be safe than sorry.
217+
// For now, this restriction is ok, since it's only called by CDP on
218+
// createBrowserContext, at which point, if we do have an active connection,
219+
// that's probably a bug (a previous abort failed?). But if we need to call this
220+
// at any point in time, it could be worth digging into libcurl to see if this
221+
// can be changed at any point in the easy's lifecycle.
222+
pub fn changeProxy(self: *Client, proxy: [:0]const u8) !void {
223+
try self.ensureNoActiveConnection();
224+
225+
for (self.handles.handles) |h| {
226+
try errorCheck(c.curl_easy_setopt(h.conn.easy, c.CURLOPT_PROXY, proxy.ptr));
227+
}
228+
try errorCheck(c.curl_easy_setopt(self.blocking.conn.easy, c.CURLOPT_PROXY, proxy.ptr));
229+
}
230+
231+
// Same restriction as changeProxy. Should be ok since this is only called on
232+
// BrowserContext deinit.
233+
pub fn restoreOriginalProxy(self: *Client) !void {
234+
try self.ensureNoActiveConnection();
235+
236+
const proxy = if (self.http_proxy) |p| p.ptr else null;
237+
for (self.handles.handles) |h| {
238+
try errorCheck(c.curl_easy_setopt(h.conn.easy, c.CURLOPT_PROXY, proxy));
239+
}
240+
try errorCheck(c.curl_easy_setopt(self.blocking.conn.easy, c.CURLOPT_PROXY, proxy));
241+
}
242+
211243
fn makeRequest(self: *Client, handle: *Handle, req: Request) !void {
212244
const conn = handle.conn;
213245
const easy = conn.easy;
@@ -339,6 +371,17 @@ fn endTransfer(self: *Client, transfer: *Transfer) void {
339371
self.active -= 1;
340372
}
341373

374+
fn ensureNoActiveConnection(self: *const Client) !void {
375+
if (self.active > 0) {
376+
return error.InflightConnection;
377+
}
378+
if (comptime builtin.mode == .Debug) {
379+
if (self.blocking_active) {
380+
return error.InflightConnection;
381+
}
382+
}
383+
}
384+
342385
const Handles = struct {
343386
handles: []Handle,
344387
in_use: HandleList,

src/main.zig

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ const Command = struct {
253253
};
254254

255255
fn printUsageAndExit(self: *const Command, success: bool) void {
256-
// MAX_HELP_LEN|
256+
// MAX_HELP_LEN|
257257
const common_options =
258258
\\
259259
\\--insecure_disable_tls_host_verification
@@ -298,7 +298,7 @@ const Command = struct {
298298
\\
299299
;
300300

301-
// MAX_HELP_LEN|
301+
// MAX_HELP_LEN|
302302
const usage =
303303
\\usage: {s} command [options] [URL]
304304
\\
@@ -749,7 +749,7 @@ fn serveCDP(address: std.net.Address, platform: *const Platform) !void {
749749
.run_mode = .serve,
750750
.tls_verify_host = false,
751751
.platform = platform,
752-
.max_concurrent_transfers = 2,
752+
.http_max_concurrent = 2,
753753
});
754754
defer app.deinit();
755755

0 commit comments

Comments
 (0)