mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-10-29 07:03:29 +00:00
Add --user_agent_suffix argument
Allows appending a value (separated by a space) to the existing Lightpanda/X.Y user agent.
This commit is contained in:
@@ -36,6 +36,7 @@ pub const App = struct {
|
|||||||
http_connect_timeout_ms: ?u31 = null,
|
http_connect_timeout_ms: ?u31 = null,
|
||||||
http_max_host_open: ?u8 = null,
|
http_max_host_open: ?u8 = null,
|
||||||
http_max_concurrent: ?u8 = null,
|
http_max_concurrent: ?u8 = null,
|
||||||
|
user_agent: [:0]const u8,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn init(allocator: Allocator, config: Config) !*App {
|
pub fn init(allocator: Allocator, config: Config) !*App {
|
||||||
@@ -53,6 +54,7 @@ pub const App = struct {
|
|||||||
.http_proxy = config.http_proxy,
|
.http_proxy = config.http_proxy,
|
||||||
.tls_verify_host = config.tls_verify_host,
|
.tls_verify_host = config.tls_verify_host,
|
||||||
.proxy_bearer_token = config.proxy_bearer_token,
|
.proxy_bearer_token = config.proxy_bearer_token,
|
||||||
|
.user_agent = config.user_agent,
|
||||||
});
|
});
|
||||||
errdefer http.deinit();
|
errdefer http.deinit();
|
||||||
|
|
||||||
|
|||||||
@@ -205,7 +205,7 @@ pub fn addFromElement(self: *ScriptManager, element: *parser.Element) !void {
|
|||||||
|
|
||||||
errdefer pending_script.deinit();
|
errdefer pending_script.deinit();
|
||||||
|
|
||||||
var headers = try Http.Headers.init();
|
var headers = try self.client.newHeaders();
|
||||||
try page.requestCookie(.{}).headersForRequest(page.arena, remote_url.?, &headers);
|
try page.requestCookie(.{}).headersForRequest(page.arena, remote_url.?, &headers);
|
||||||
|
|
||||||
try self.client.request(.{
|
try self.client.request(.{
|
||||||
@@ -273,7 +273,7 @@ pub fn blockingGet(self: *ScriptManager, url: [:0]const u8) !BlockingResult {
|
|||||||
.buffer_pool = &self.buffer_pool,
|
.buffer_pool = &self.buffer_pool,
|
||||||
};
|
};
|
||||||
|
|
||||||
var headers = try Http.Headers.init();
|
var headers = try self.client.newHeaders();
|
||||||
try self.page.requestCookie(.{}).headersForRequest(self.page.arena, url, &headers);
|
try self.page.requestCookie(.{}).headersForRequest(self.page.arena, url, &headers);
|
||||||
|
|
||||||
var client = self.client;
|
var client = self.client;
|
||||||
|
|||||||
@@ -548,7 +548,7 @@ pub const Page = struct {
|
|||||||
const owned_url = try self.arena.dupeZ(u8, request_url);
|
const owned_url = try self.arena.dupeZ(u8, request_url);
|
||||||
self.url = try URL.parse(owned_url, null);
|
self.url = try URL.parse(owned_url, null);
|
||||||
|
|
||||||
var headers = try Http.Headers.init();
|
var headers = try self.http_client.newHeaders();
|
||||||
if (opts.header) |hdr| try headers.add(hdr);
|
if (opts.header) |hdr| try headers.add(hdr);
|
||||||
try self.requestCookie(.{ .is_navigation = true }).headersForRequest(self.arena, owned_url, &headers);
|
try self.requestCookie(.{ .is_navigation = true }).headersForRequest(self.arena, owned_url, &headers);
|
||||||
|
|
||||||
|
|||||||
@@ -370,7 +370,7 @@ pub const XMLHttpRequest = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var headers = try Http.Headers.init();
|
var headers = try page.http_client.newHeaders();
|
||||||
for (self.headers.items) |hdr| {
|
for (self.headers.items) |hdr| {
|
||||||
try headers.add(hdr);
|
try headers.add(hdr);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,6 +96,9 @@ notification: ?*Notification = null,
|
|||||||
// restoring, this originally-configured value is what it goes to.
|
// restoring, this originally-configured value is what it goes to.
|
||||||
http_proxy: ?[:0]const u8 = null,
|
http_proxy: ?[:0]const u8 = null,
|
||||||
|
|
||||||
|
// The complete user-agent header line
|
||||||
|
user_agent: [:0]const u8,
|
||||||
|
|
||||||
// libcurl can monitor arbitrary sockets. Currently, we ever [maybe] want to
|
// libcurl can monitor arbitrary sockets. Currently, we ever [maybe] want to
|
||||||
// monitor the CDP client socket, so we've done the simplest thing possible
|
// monitor the CDP client socket, so we've done the simplest thing possible
|
||||||
// by having this single optional field
|
// by having this single optional field
|
||||||
@@ -130,6 +133,7 @@ pub fn init(allocator: Allocator, ca_blob: ?c.curl_blob, opts: Http.Opts) !*Clie
|
|||||||
.blocking = blocking,
|
.blocking = blocking,
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
.http_proxy = opts.http_proxy,
|
.http_proxy = opts.http_proxy,
|
||||||
|
.user_agent = opts.user_agent,
|
||||||
.transfer_pool = transfer_pool,
|
.transfer_pool = transfer_pool,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -147,6 +151,10 @@ pub fn deinit(self: *Client) void {
|
|||||||
self.allocator.destroy(self);
|
self.allocator.destroy(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn newHeaders(self: *const Client) !Http.Headers {
|
||||||
|
return Http.Headers.init(self.user_agent);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn abort(self: *Client) void {
|
pub fn abort(self: *Client) void {
|
||||||
while (self.handles.in_use.first) |node| {
|
while (self.handles.in_use.first) |node| {
|
||||||
const handle: *Handle = @fieldParentPtr("node", node);
|
const handle: *Handle = @fieldParentPtr("node", node);
|
||||||
@@ -796,7 +804,7 @@ pub const Transfer = struct {
|
|||||||
self.req.headers.deinit();
|
self.req.headers.deinit();
|
||||||
|
|
||||||
var buf: std.ArrayListUnmanaged(u8) = .empty;
|
var buf: std.ArrayListUnmanaged(u8) = .empty;
|
||||||
var new_headers = try Http.Headers.init();
|
var new_headers = try self.client.newHeaders();
|
||||||
for (headers) |hdr| {
|
for (headers) |hdr| {
|
||||||
// safe to re-use this buffer, because Headers.add because curl copies
|
// safe to re-use this buffer, because Headers.add because curl copies
|
||||||
// the value we pass into curl_slist_append.
|
// the value we pass into curl_slist_append.
|
||||||
|
|||||||
@@ -102,6 +102,10 @@ pub fn newConnection(self: *Http) !Connection {
|
|||||||
return Connection.init(self.ca_blob, &self.opts);
|
return Connection.init(self.ca_blob, &self.opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn newHeaders(self: *const Http) Headers {
|
||||||
|
return Headers.init(self.opts.user_agent);
|
||||||
|
}
|
||||||
|
|
||||||
pub const Connection = struct {
|
pub const Connection = struct {
|
||||||
easy: *c.CURL,
|
easy: *c.CURL,
|
||||||
opts: Connection.Opts,
|
opts: Connection.Opts,
|
||||||
@@ -259,8 +263,8 @@ pub const Headers = struct {
|
|||||||
headers: *c.curl_slist,
|
headers: *c.curl_slist,
|
||||||
cookies: ?[*c]const u8,
|
cookies: ?[*c]const u8,
|
||||||
|
|
||||||
pub fn init() !Headers {
|
pub fn init(user_agent: [:0]const u8) !Headers {
|
||||||
const header_list = c.curl_slist_append(null, "User-Agent: Lightpanda/1.0");
|
const header_list = c.curl_slist_append(null, user_agent);
|
||||||
if (header_list == null) return error.OutOfMemory;
|
if (header_list == null) return error.OutOfMemory;
|
||||||
return .{ .headers = header_list, .cookies = null };
|
return .{ .headers = header_list, .cookies = null };
|
||||||
}
|
}
|
||||||
@@ -337,6 +341,7 @@ pub const Opts = struct {
|
|||||||
tls_verify_host: bool = true,
|
tls_verify_host: bool = true,
|
||||||
http_proxy: ?[:0]const u8 = null,
|
http_proxy: ?[:0]const u8 = null,
|
||||||
proxy_bearer_token: ?[:0]const u8 = null,
|
proxy_bearer_token: ?[:0]const u8 = null,
|
||||||
|
user_agent: [:0]const u8,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Method = enum {
|
pub const Method = enum {
|
||||||
|
|||||||
35
src/main.zig
35
src/main.zig
@@ -108,6 +108,14 @@ fn run(alloc: Allocator) !void {
|
|||||||
log.opts.filter_scopes = lfs;
|
log.opts.filter_scopes = lfs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const user_agent = blk: {
|
||||||
|
const USER_AGENT = "User-Agent: Lightpanda/1.0";
|
||||||
|
if (args.userAgentSuffix()) |suffix| {
|
||||||
|
break :blk try std.fmt.allocPrintSentinel(args_arena.allocator(), "{s} {s}", .{ USER_AGENT, suffix }, 0);
|
||||||
|
}
|
||||||
|
break :blk USER_AGENT;
|
||||||
|
};
|
||||||
|
|
||||||
// _app is global to handle graceful shutdown.
|
// _app is global to handle graceful shutdown.
|
||||||
_app = try App.init(alloc, .{
|
_app = try App.init(alloc, .{
|
||||||
.run_mode = args.mode,
|
.run_mode = args.mode,
|
||||||
@@ -118,6 +126,7 @@ fn run(alloc: Allocator) !void {
|
|||||||
.http_connect_timeout_ms = args.httpConnectTiemout(),
|
.http_connect_timeout_ms = args.httpConnectTiemout(),
|
||||||
.http_max_host_open = args.httpMaxHostOpen(),
|
.http_max_host_open = args.httpMaxHostOpen(),
|
||||||
.http_max_concurrent = args.httpMaxConcurrent(),
|
.http_max_concurrent = args.httpMaxConcurrent(),
|
||||||
|
.user_agent = user_agent,
|
||||||
});
|
});
|
||||||
|
|
||||||
const app = _app.?;
|
const app = _app.?;
|
||||||
@@ -260,6 +269,13 @@ const Command = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn userAgentSuffix(self: *const Command) ?[]const u8 {
|
||||||
|
return switch (self.mode) {
|
||||||
|
inline .serve, .fetch => |opts| opts.common.user_agent_suffix,
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const Mode = union(App.RunMode) {
|
const Mode = union(App.RunMode) {
|
||||||
help: bool, // false when being printed because of an error
|
help: bool, // false when being printed because of an error
|
||||||
fetch: Fetch,
|
fetch: Fetch,
|
||||||
@@ -293,6 +309,7 @@ const Command = struct {
|
|||||||
log_level: ?log.Level = null,
|
log_level: ?log.Level = null,
|
||||||
log_format: ?log.Format = null,
|
log_format: ?log.Format = null,
|
||||||
log_filter_scopes: ?[]log.Scope = null,
|
log_filter_scopes: ?[]log.Scope = null,
|
||||||
|
user_agent_suffix: ?[]const u8 = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn printUsageAndExit(self: *const Command, success: bool) void {
|
fn printUsageAndExit(self: *const Command, success: bool) void {
|
||||||
@@ -339,6 +356,9 @@ const Command = struct {
|
|||||||
\\ Defaults to
|
\\ Defaults to
|
||||||
++ (if (builtin.mode == .Debug) " pretty." else " logfmt.") ++
|
++ (if (builtin.mode == .Debug) " pretty." else " logfmt.") ++
|
||||||
\\
|
\\
|
||||||
|
\\ --user_agent_suffix
|
||||||
|
\\ Suffix to append to the Lightpanda/X.Y User-Agent
|
||||||
|
\\
|
||||||
;
|
;
|
||||||
|
|
||||||
// MAX_HELP_LEN|
|
// MAX_HELP_LEN|
|
||||||
@@ -713,6 +733,21 @@ fn parseCommonArg(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (std.mem.eql(u8, "--user_agent_suffix", opt)) {
|
||||||
|
const str = args.next() orelse {
|
||||||
|
log.fatal(.app, "missing argument value", .{ .arg = "--user_agent_suffix" });
|
||||||
|
return error.InvalidArgument;
|
||||||
|
};
|
||||||
|
for (str) |c| {
|
||||||
|
if (!std.ascii.isPrint(c)) {
|
||||||
|
log.fatal(.app, "not printable character", .{ .arg = "--user_agent_suffix" });
|
||||||
|
return error.InvalidArgument;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
common.user_agent_suffix = try allocator.dupe(u8, str);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -493,6 +493,7 @@ pub fn setup() !void {
|
|||||||
test_app = try App.init(gpa.allocator(), .{
|
test_app = try App.init(gpa.allocator(), .{
|
||||||
.run_mode = .serve,
|
.run_mode = .serve,
|
||||||
.tls_verify_host = false,
|
.tls_verify_host = false,
|
||||||
|
.user_agent = "User-Agent: Lightpanda/1.0 internal-tester",
|
||||||
});
|
});
|
||||||
errdefer test_app.deinit();
|
errdefer test_app.deinit();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user