Skip to content

Commit 6360383

Browse files
committed
feat: add --user-agent flag for full User-Agent override
When --user-agent is set, the provided string replaces the entire User-Agent header instead of appending to "Lightpanda/1.0". The existing --user-agent-suffix behavior is unchanged. Fixes #2029
1 parent 7a23686 commit 6360383

1 file changed

Lines changed: 30 additions & 2 deletions

File tree

src/Config.zig

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,13 @@ pub fn userAgentSuffix(self: *const Config) ?[]const u8 {
156156
};
157157
}
158158

159+
pub fn userAgent(self: *const Config) ?[]const u8 {
160+
return switch (self.mode) {
161+
inline .serve, .fetch, .mcp => |opts| opts.common.user_agent,
162+
.help, .version => null,
163+
};
164+
}
165+
159166
pub fn cdpTimeout(self: *const Config) usize {
160167
return switch (self.mode) {
161168
.serve => |opts| if (opts.timeout > 604_800) 604_800_000 else @as(usize, opts.timeout) * 1000,
@@ -264,6 +271,7 @@ pub const Common = struct {
264271
log_format: ?log.Format = null,
265272
log_filter_scopes: ?[]log.Scope = null,
266273
user_agent_suffix: ?[]const u8 = null,
274+
user_agent: ?[]const u8 = null,
267275

268276
web_bot_auth_key_file: ?[]const u8 = null,
269277
web_bot_auth_keyid: ?[]const u8 = null,
@@ -281,11 +289,14 @@ pub const HttpHeaders = struct {
281289
proxy_bearer_header: ?[:0]const u8,
282290

283291
pub fn init(allocator: Allocator, config: *const Config) !HttpHeaders {
284-
const user_agent: [:0]const u8 = if (config.userAgentSuffix()) |suffix|
292+
const ua_needs_free = config.userAgent() != null or config.userAgentSuffix() != null;
293+
const user_agent: [:0]const u8 = if (config.userAgent()) |ua|
294+
try allocator.dupeZ(u8, ua)
295+
else if (config.userAgentSuffix()) |suffix|
285296
try std.fmt.allocPrintSentinel(allocator, "{s} {s}", .{ user_agent_base, suffix }, 0)
286297
else
287298
user_agent_base;
288-
errdefer if (config.userAgentSuffix() != null) allocator.free(user_agent);
299+
errdefer if (ua_needs_free) allocator.free(user_agent);
289300

290301
const user_agent_header = try std.fmt.allocPrintSentinel(allocator, "User-Agent: {s}", .{user_agent}, 0);
291302
errdefer allocator.free(user_agent_header);
@@ -372,6 +383,8 @@ pub fn printUsageAndExit(self: *const Config, success: bool) void {
372383
\\ Filter out too verbose logs per scope:
373384
\\ http, unknown_prop, event, ...
374385
\\
386+
\\--user-agent Override the User-Agent header entirely
387+
\\
375388
\\--user-agent-suffix
376389
\\ Suffix to append to the Lightpanda/X.Y User-Agent
377390
\\
@@ -938,6 +951,21 @@ fn parseCommonArg(
938951
return true;
939952
}
940953

954+
if (std.mem.eql(u8, "--user-agent", opt) or std.mem.eql(u8, "--user_agent", opt)) {
955+
const str = args.next() orelse {
956+
log.fatal(.app, "missing argument value", .{ .arg = opt });
957+
return error.InvalidArgument;
958+
};
959+
for (str) |c| {
960+
if (!std.ascii.isPrint(c)) {
961+
log.fatal(.app, "not printable character", .{ .arg = opt });
962+
return error.InvalidArgument;
963+
}
964+
}
965+
common.user_agent = try allocator.dupe(u8, str);
966+
return true;
967+
}
968+
941969
if (std.mem.eql(u8, "--user-agent-suffix", opt) or std.mem.eql(u8, "--user_agent_suffix", opt)) {
942970
const str = args.next() orelse {
943971
log.fatal(.app, "missing argument value", .{ .arg = opt });

0 commit comments

Comments
 (0)