add isSameOrigin to URL

This commit is contained in:
Muki Kiboigo
2026-07-18 11:59:38 -07:00
parent 3e3825108d
commit d4d8381ecb

View File

@@ -341,6 +341,11 @@ pub fn getOrigin(allocator: Allocator, raw: [:0]const u8) !?[]const u8 {
return raw[0..authority_end];
}
pub fn isSameOrigin(url: [:0]const u8, origin: [:0]const u8) bool {
return std.mem.eql(u8, getProtocol(url), getProtocol(origin)) and
std.mem.eql(u8, getHost(url), getHost(origin));
}
fn getUserInfo(raw: [:0]const u8) ?[]const u8 {
const auth = parseAuthority(raw) orelse return null;
if (!auth.has_user_info) return null;
@@ -1500,6 +1505,56 @@ test "URL: getOrigin" {
}
}
test "URL: isSameOrigin" {
const Case = struct {
url: [:0]const u8,
origin: [:0]const u8,
expected: bool,
};
const cases = [_]Case{
// Identical origins
.{ .url = "https://example.com/path", .origin = "https://example.com", .expected = true },
.{ .url = "https://example.com", .origin = "https://example.com", .expected = true },
// Different scheme
.{ .url = "http://example.com/path", .origin = "https://example.com", .expected = false },
// Different host
.{ .url = "https://example.org/path", .origin = "https://example.com", .expected = false },
// Subdomain is a different origin
.{ .url = "https://sub.example.com/path", .origin = "https://example.com", .expected = false },
// Fastpath false-positive guard: url's host is NOT origin's host,
// even though origin is a literal string prefix of url.
.{ .url = "https://example.com.evil.com/path", .origin = "https://example.com", .expected = false },
// Same host, different port
.{ .url = "https://example.com:8080/path", .origin = "https://example.com", .expected = false },
.{ .url = "https://example.com:8080/path", .origin = "https://example.com:8080", .expected = true },
.{ .url = "https://example.com:8080/path", .origin = "https://example.com:9090", .expected = false },
// origin as a full URL (not just an origin serialization) still works
.{ .url = "https://example.com/a", .origin = "https://example.com/b?x=1", .expected = true },
// userinfo on url must not affect the comparison
.{ .url = "https://user:pass@example.com/path", .origin = "https://example.com", .expected = true },
// path/query/fragment differences are irrelevant to origin
.{ .url = "https://example.com/a/b?x=1#f", .origin = "https://example.com/", .expected = true },
// IPv6 hosts
.{ .url = "https://[::1]:8080/path", .origin = "https://[::1]:8080", .expected = true },
.{ .url = "https://[::1]:8080/path", .origin = "https://[::1]:9090", .expected = false },
.{ .url = "https://[::1]/path", .origin = "https://[2001:db8::1]/", .expected = false },
};
for (cases) |case| {
try testing.expectEqual(case.expected, isSameOrigin(case.url, case.origin));
}
}
test "URL: resolve path scheme" {
const Case = struct {
base: [:0]const u8,