@@ -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+
159166pub 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