From 14f1ef35f14a36bfee84dff66df12ec269097335 Mon Sep 17 00:00:00 2001 From: Karl Seguin Date: Mon, 1 Jun 2026 08:35:19 +0800 Subject: [PATCH] URL.isHTTPs -> URL.isSecure and consider wss:// Use conn.setCookie in websocket --- src/browser/HttpClient.zig | 8 ++++--- src/browser/URL.zig | 4 ++-- src/browser/webapi/net/WebSocket.zig | 27 ++++++++++------------ src/browser/webapi/storage/Cookie.zig | 2 +- src/browser/webapi/storage/CookieStore.zig | 6 ++--- src/cdp/domains/network.zig | 2 +- src/cdp/domains/storage.zig | 2 +- 7 files changed, 25 insertions(+), 26 deletions(-) diff --git a/src/browser/HttpClient.zig b/src/browser/HttpClient.zig index 81c4dc14..6eb3611e 100644 --- a/src/browser/HttpClient.zig +++ b/src/browser/HttpClient.zig @@ -1247,10 +1247,12 @@ pub const Request = struct { .origin_url = self.cookie_origin, .is_navigation = self.resource_type == .document, }); - const written = aw.written(); - if (written.len == 0) return null; + if (aw.written().len == 0) { + return null; + } try aw.writer.writeByte(0); - return written.ptr[0..written.len :0]; + const written = aw.written(); + return written.ptr[0 .. written.len - 1 :0]; } pub fn deinit(self: *const Request) void { diff --git a/src/browser/URL.zig b/src/browser/URL.zig index 620e63a2..f2650164 100644 --- a/src/browser/URL.zig +++ b/src/browser/URL.zig @@ -464,8 +464,8 @@ pub fn getProtocol(raw: [:0]const u8) []const u8 { return raw[0 .. pos + 1]; } -pub fn isHTTPS(raw: [:0]const u8) bool { - return std.mem.startsWith(u8, raw, "https:"); +pub fn isSecure(raw: [:0]const u8) bool { + return std.mem.startsWith(u8, raw, "https:") or std.mem.startsWith(u8, raw, "wss:"); } pub fn getHostname(raw: [:0]const u8) []const u8 { diff --git a/src/browser/webapi/net/WebSocket.zig b/src/browser/webapi/net/WebSocket.zig index 7c9c7f54..c80b520f 100644 --- a/src/browser/webapi/net/WebSocket.zig +++ b/src/browser/webapi/net/WebSocket.zig @@ -141,21 +141,18 @@ pub fn init(url: []const u8, protocols: [][]const u8, exec: *const Execution) !* has_extra_headers = true; } - // Attach matching cookies from the session jar. Real browsers send - // cookies on the WebSocket upgrade request just like any other - // same-origin HTTP request — without this, server-side session - // checks (Phoenix LiveView, anything cookie-authenticated) reject - // the upgrade. - var cookie_buf: std.Io.Writer.Allocating = .init(arena); - try exec.session.cookie_jar.forRequest(resolved_url, &cookie_buf.writer, .{ - .is_http = true, - .is_navigation = false, - .origin_url = exec.url.*, - }); - if (cookie_buf.written().len > 0) { - const cookie_header = try std.fmt.allocPrintSentinel(arena, "Cookie: {s}", .{cookie_buf.written()}, 0); - try headers.add(cookie_header); - has_extra_headers = true; + { + var buf: std.Io.Writer.Allocating = .init(arena); + try exec.session.cookie_jar.forRequest(resolved_url, &buf.writer, .{ + .is_http = true, + .is_navigation = false, + .origin_url = exec.url.*, + }); + if (buf.written().len > 0) { + try buf.writer.writeByte(0); + const written = buf.written(); + try conn.setCookies(written.ptr[0 .. written.len - 1 :0]); + } } if (has_extra_headers) { diff --git a/src/browser/webapi/storage/Cookie.zig b/src/browser/webapi/storage/Cookie.zig index 0e023705..b7c721ea 100644 --- a/src/browser/webapi/storage/Cookie.zig +++ b/src/browser/webapi/storage/Cookie.zig @@ -577,7 +577,7 @@ pub const Jar = struct { const target = PreparedUri{ .host = URL.getHostname(target_url), .path = URL.getPathname(target_url), - .secure = URL.isHTTPS(target_url), + .secure = URL.isSecure(target_url), }; const same_site = try areSameSite(opts.origin_url, target.host); diff --git a/src/browser/webapi/storage/CookieStore.zig b/src/browser/webapi/storage/CookieStore.zig index 4d679e54..cf365537 100644 --- a/src/browser/webapi/storage/CookieStore.zig +++ b/src/browser/webapi/storage/CookieStore.zig @@ -76,7 +76,7 @@ fn onCookieChanged(ctx: *anyopaque, data: *const Notification.CookieChanged) !vo const target = Cookie.PreparedUri{ .host = URL.getHostname(doc_url), .path = URL.getPathname(doc_url), - .secure = URL.isHTTPS(doc_url), + .secure = URL.isSecure(doc_url), }; if (target.host.len == 0) return; @@ -353,7 +353,7 @@ fn matchCookies( const target = Cookie.PreparedUri{ .host = URL.getHostname(url_resolved), .path = URL.getPathname(url_resolved), - .secure = URL.isHTTPS(url_resolved), + .secure = URL.isSecure(url_resolved), }; if (target.host.len == 0) return error.SecurityError; @@ -408,7 +408,7 @@ fn storeCookie(exec: *const Execution, init: CookieInit) !void { if (std.mem.indexOfAny(u8, d, ";\r\n\x00") != null) return error.InvalidCookieDomain; } - const is_https = URL.isHTTPS(url); + const is_https = URL.isSecure(url); // Per spec, SameSite=None requires Secure. CookieStore additionally // marks any cookie written from an HTTPS document as Secure. const secure = is_https or init.sameSite == .none; diff --git a/src/cdp/domains/network.zig b/src/cdp/domains/network.zig index 5a33df88..864c72f5 100644 --- a/src/cdp/domains/network.zig +++ b/src/cdp/domains/network.zig @@ -233,7 +233,7 @@ fn getCookies(cmd: *CDP.Command) !void { urls.appendAssumeCapacity(.{ .host = try Cookie.parseDomain(cmd.arena, url, null), .path = try Cookie.parsePath(cmd.arena, url, null), - .secure = URL.isHTTPS(url), + .secure = URL.isSecure(url), }); } diff --git a/src/cdp/domains/storage.zig b/src/cdp/domains/storage.zig index dac20e10..7e38c132 100644 --- a/src/cdp/domains/storage.zig +++ b/src/cdp/domains/storage.zig @@ -153,7 +153,7 @@ pub fn setCdpCookie(cookie_jar: *CookieJar, param: CdpCookie) !void { const domain = try Cookie.parseDomain(a, param.url, param.domain); const path = if (param.path == null) "/" else try Cookie.parsePath(a, null, param.path); - const secure = if (param.secure) |s| s else if (param.url) |url| URL.isHTTPS(url) else false; + const secure = if (param.secure) |s| s else if (param.url) |url| URL.isSecure(url) else false; break :blk Cookie{ .arena = arena,