Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions src/app.zig
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,18 @@ pub const App = struct {
app_dir_path: ?[]const u8,

pub const RunMode = enum {
serve,
help,
fetch,
serve,
version,
};

pub const Config = struct {
tls_verify_host: bool = true,
run_mode: RunMode,
};

pub fn init(allocator: Allocator, run_mode: RunMode) !*App {
pub fn init(allocator: Allocator, config: Config) !*App {
const app = try allocator.create(App);
errdefer allocator.destroy(app);

Expand All @@ -38,9 +45,11 @@ pub const App = struct {
.allocator = allocator,
.telemetry = undefined,
.app_dir_path = app_dir_path,
.http_client = try HttpClient.init(allocator, 5),
.http_client = try HttpClient.init(allocator, 5, .{
.tls_verify_host = config.tls_verify_host,
}),
};
app.telemetry = Telemetry.init(app, run_mode);
app.telemetry = Telemetry.init(app, config.run_mode);

return app;
}
Expand Down
2 changes: 1 addition & 1 deletion src/cdp/testing.zig
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ const TestContext = struct {

pub fn context() TestContext {
return .{
.app = App.init(std.testing.allocator, .serve) catch unreachable,
.app = App.init(std.testing.allocator, .{ .run_mode = .serve }) catch unreachable,
.arena = std.heap.ArenaAllocator.init(std.testing.allocator),
};
}
Expand Down
26 changes: 18 additions & 8 deletions src/http/client.zig
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,13 @@ pub const Client = struct {
allocator: Allocator,
state_pool: StatePool,
root_ca: tls.config.CertBundle,
tls_verify_host: bool = true,

// we only allow passing in a root_ca for testing
pub fn init(allocator: Allocator, max_concurrent: usize) !Client {
const Opts = struct {
tls_verify_host: bool = true,
};

pub fn init(allocator: Allocator, max_concurrent: usize, opts: Opts) !Client {
var root_ca = try tls.config.CertBundle.fromSystem(allocator);
errdefer root_ca.deinit(allocator);

Expand All @@ -58,6 +62,7 @@ pub const Client = struct {
.root_ca = root_ca,
.allocator = allocator,
.state_pool = state_pool,
.tls_verify_host = opts.tls_verify_host,
};
}

Expand Down Expand Up @@ -123,7 +128,7 @@ pub const Request = struct {
_has_host_header: bool,

// Whether or not we should verify that the host matches the certificate CN
_tls_verify_host: bool = true,
_tls_verify_host: bool,

pub const Method = enum {
GET,
Expand Down Expand Up @@ -167,6 +172,7 @@ pub const Request = struct {
._client = client,
._redirect_count = 0,
._has_host_header = false,
._tls_verify_host = client.tls_verify_host,
};
}

Expand Down Expand Up @@ -205,11 +211,13 @@ pub const Request = struct {

// TODO timeout
const SendSyncOpts = struct {
tls_verify_host: bool = true,
tls_verify_host: ?bool = null,
};
// Makes an synchronous request
pub fn sendSync(self: *Request, opts: SendSyncOpts) anyerror!Response {
self._tls_verify_host = opts.tls_verify_host;
if (opts.tls_verify_host) |override| {
self._tls_verify_host = override;
}
try self.prepareInitialSend();
return self.doSendSync();
}
Expand All @@ -230,11 +238,13 @@ pub const Request = struct {
}

const SendAsyncOpts = struct {
tls_verify_host: bool = true,
tls_verify_host: ?bool = null,
};
// Makes an asynchronous request
pub fn sendAsync(self: *Request, loop: anytype, handler: anytype, opts: SendAsyncOpts) !void {
self._tls_verify_host = opts.tls_verify_host;
if (opts.tls_verify_host) |override| {
self._tls_verify_host = override;
}
try self.prepareInitialSend();
return self.doSendAsync(loop, handler);
}
Expand Down Expand Up @@ -2176,5 +2186,5 @@ fn testReader(state: *State, res: *TestResponse, data: []const u8) !void {
}

fn testClient() !Client {
return try Client.init(testing.allocator, 1);
return try Client.init(testing.allocator, 1, .{});
}
60 changes: 46 additions & 14 deletions src/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const Allocator = std.mem.Allocator;

const jsruntime = @import("jsruntime");

const App = @import("app.zig").App;
const Browser = @import("browser/browser.zig").Browser;
const server = @import("server.zig");

Expand Down Expand Up @@ -69,9 +70,12 @@ pub fn main() !void {
log.err("address (host:port) {any}\n", .{err});
return args.printUsageAndExit(false);
};

var app = try @import("app.zig").App.init(alloc, .serve);
var app = try App.init(alloc, .{
.run_mode = args.mode,
.tls_verify_host = opts.tls_verify_host,
});
defer app.deinit();

app.telemetry.record(.{ .run = {} });

const timeout = std.time.ns_per_s * @as(u64, opts.timeout);
Expand All @@ -83,7 +87,10 @@ pub fn main() !void {
.fetch => |opts| {
log.debug("Fetch mode: url {s}, dump {any}", .{ opts.url, opts.dump });

var app = try @import("app.zig").App.init(alloc, .fetch);
var app = try App.init(alloc, .{
.run_mode = args.mode,
.tls_verify_host = opts.tls_verify_host,
});
defer app.deinit();
app.telemetry.record(.{ .run = {} });

Expand Down Expand Up @@ -125,14 +132,7 @@ const Command = struct {
mode: Mode,
exec_name: []const u8,

const ModeType = enum {
help,
fetch,
serve,
version,
};

const Mode = union(ModeType) {
const Mode = union(App.RunMode) {
help: bool, // false when being printed because of an error
fetch: Fetch,
serve: Serve,
Expand All @@ -143,11 +143,13 @@ const Command = struct {
host: []const u8,
port: u16,
timeout: u16,
tls_verify_host: bool,
};

const Fetch = struct {
url: []const u8,
dump: bool = false,
tls_verify_host: bool,
};

fn printUsageAndExit(self: *const Command, success: bool) void {
Expand All @@ -164,6 +166,12 @@ const Command = struct {
\\--dump Dumps document to stdout.
\\ Defaults to false.
\\
\\--insecure_disable_tls_host_verification
\\ Disables host verification on all HTTP requests.
\\ This is an advanced option which should only be
\\ set if you understand and accept the risk of
\\ disabling host verification.
\\
\\serve command
\\Starts a websocket CDP server
\\Example: {s} serve --host 127.0.0.1 --port 9222
Expand All @@ -178,11 +186,18 @@ const Command = struct {
\\--timeout Inactivity timeout in seconds before disconnecting clients
\\ Defaults to 3 (seconds)
\\
\\--insecure_disable_tls_host_verification
\\ Disables host verification on all HTTP requests.
\\ This is an advanced option which should only be
\\ set if you understand and accept the risk of
\\ disabling host verification.
\\
\\version command
\\Displays the version of {s}
\\
\\help command
\\Displays this message
\\
;
std.debug.print(usage, .{ self.exec_name, self.exec_name, self.exec_name, self.exec_name });
if (success) {
Expand All @@ -204,7 +219,7 @@ fn parseArgs(allocator: Allocator) !Command {
};

const mode_string = args.next() orelse "";
const mode = std.meta.stringToEnum(Command.ModeType, mode_string) orelse blk: {
const mode = std.meta.stringToEnum(App.RunMode, mode_string) orelse blk: {
const inferred_mode = inferMode(mode_string) orelse return cmd;
// "command" wasn't a command but an option. We can't reset args, but
// we can create a new one. Not great, but this fallback is temporary
Expand All @@ -227,7 +242,7 @@ fn parseArgs(allocator: Allocator) !Command {
return cmd;
}

fn inferMode(opt: []const u8) ?Command.ModeType {
fn inferMode(opt: []const u8) ?App.RunMode {
if (opt.len == 0) {
return .serve;
}
Expand Down Expand Up @@ -260,6 +275,7 @@ fn parseServeArgs(
var host: []const u8 = "127.0.0.1";
var port: u16 = 9222;
var timeout: u16 = 3;
var tls_verify_host = true;

while (args.next()) |opt| {
if (std.mem.eql(u8, "--host", opt)) {
Expand Down Expand Up @@ -297,6 +313,11 @@ fn parseServeArgs(
continue;
}

if (std.mem.eql(u8, "--insecure_tls_verify_host", opt)) {
tls_verify_host = false;
continue;
}

log.err("Unknown option to serve command: '{s}'", .{opt});
return error.UnkownOption;
}
Expand All @@ -305,6 +326,7 @@ fn parseServeArgs(
.host = host,
.port = port,
.timeout = timeout,
.tls_verify_host = tls_verify_host,
};
}

Expand All @@ -314,13 +336,19 @@ fn parseFetchArgs(
) !Command.Fetch {
var dump: bool = false;
var url: ?[]const u8 = null;
var tls_verify_host = true;

while (args.next()) |opt| {
if (std.mem.eql(u8, "--dump", opt)) {
dump = true;
continue;
}

if (std.mem.eql(u8, "--insecure_disable_tls_host_verification", opt)) {
tls_verify_host = false;
continue;
}

if (std.mem.startsWith(u8, opt, "--")) {
log.err("Unknown option to serve command: '{s}'", .{opt});
return error.UnkownOption;
Expand All @@ -338,7 +366,11 @@ fn parseFetchArgs(
return error.MissingURL;
}

return .{ .url = url.?, .dump = dump };
return .{
.url = url.?,
.dump = dump,
.tls_verify_host = tls_verify_host,
};
}

var verbose: bool = builtin.mode == .Debug; // In debug mode, force verbose.
Expand Down
2 changes: 1 addition & 1 deletion src/main_tests.zig
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ fn testExecFn(
std.debug.print("documentHTMLClose error: {s}\n", .{@errorName(err)});
};

var http_client = try @import("http/client.zig").Client.init(alloc, 5);
var http_client = try @import("http/client.zig").Client.init(alloc, 5, .{});
defer http_client.deinit();

try js_env.setUserContext(.{
Expand Down
2 changes: 1 addition & 1 deletion src/main_unit_tests.zig
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ fn serveHTTPS(address: std.net.Address) !void {

fn serveCDP(address: std.net.Address) !void {
const App = @import("app.zig").App;
var app = try App.init(gpa.allocator(), .serve);
var app = try App.init(gpa.allocator(), .{ .run_mode = .serve });
defer app.deinit();

const server = @import("server.zig");
Expand Down
2 changes: 1 addition & 1 deletion src/testing.zig
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ pub fn print(comptime fmt: []const u8, args: anytype) void {

// dummy opts incase we want to add something, and not have to break all the callers
pub fn app(_: anytype) *App {
return App.init(allocator, .serve) catch unreachable;
return App.init(allocator, .{ .run_mode = .serve }) catch unreachable;
}

pub const Random = struct {
Expand Down
2 changes: 1 addition & 1 deletion src/wpt/run.zig
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ pub fn run(arena: *std.heap.ArenaAllocator, comptime dir: []const u8, f: []const
var loop = try Loop.init(alloc);
defer loop.deinit();

var http_client = try HttpClient.init(alloc, 2);
var http_client = try HttpClient.init(alloc, 2, .{});
defer http_client.deinit();

var js_env: Env = undefined;
Expand Down