diff --git a/src/browser/URL.zig b/src/browser/URL.zig
index f2650164..9a87b8ed 100644
--- a/src/browser/URL.zig
+++ b/src/browser/URL.zig
@@ -121,7 +121,8 @@ pub fn resolve(allocator: Allocator, base: [:0]const u8, source_path: anytype, o
const scheme_end = std.mem.indexOf(u8, base, "://");
const authority_start = if (scheme_end) |end| end + 3 else 0;
- const path_start = std.mem.indexOfScalarPos(u8, base, authority_start, '/') orelse base.len;
+ const path_start = std.mem.indexOfAnyPos(u8, base, authority_start, "/?#") orelse base.len;
+ const path_end = std.mem.indexOfAnyPos(u8, base, path_start, "?#") orelse base.len;
if (path[0] == '/') {
const result = try std.mem.joinZ(allocator, "", &.{ base[0..path_start], path });
@@ -129,8 +130,8 @@ pub fn resolve(allocator: Allocator, base: [:0]const u8, source_path: anytype, o
}
var normalized_base: []const u8 = base[0..path_start];
- if (path_start < base.len) {
- if (std.mem.lastIndexOfScalar(u8, base[path_start + 1 ..], '/')) |pos| {
+ if (path_start < path_end) {
+ if (std.mem.lastIndexOfScalar(u8, base[path_start + 1 .. path_end], '/')) |pos| {
normalized_base = base[0 .. path_start + 1 + pos];
}
}
@@ -973,6 +974,66 @@ test "URL: resolve" {
.path = "something.js",
.expected = "https://example/xyz/abc/something.js",
},
+ .{
+ .base = "http://127.0.0.1:8123/#/login",
+ .path = "api/users/login",
+ .expected = "http://127.0.0.1:8123/api/users/login",
+ },
+ .{
+ .base = "https://example/app/page?next=/foo/bar",
+ .path = "api/users/login",
+ .expected = "https://example/app/api/users/login",
+ },
+ .{
+ .base = "https://example/app/page#/foo/bar",
+ .path = "api/users/login",
+ .expected = "https://example/app/api/users/login",
+ },
+ .{
+ .base = "https://example?next=/foo/bar",
+ .path = "api/users/login",
+ .expected = "https://example/api/users/login",
+ },
+ .{
+ .base = "https://example#/foo/bar",
+ .path = "api/users/login",
+ .expected = "https://example/api/users/login",
+ },
+ .{
+ .base = "https://example?next=/foo/bar",
+ .path = "/api/users/login",
+ .expected = "https://example/api/users/login",
+ },
+ .{
+ .base = "https://example/app/page?next=/foo/bar",
+ .path = "../api/users/login",
+ .expected = "https://example/api/users/login",
+ },
+ .{
+ .base = "https://example/app/page#/foo/bar",
+ .path = "../api/users/login",
+ .expected = "https://example/api/users/login",
+ },
+ .{
+ .base = "https://example/app/dir/?next=/foo/bar",
+ .path = "../api/users/login",
+ .expected = "https://example/app/api/users/login",
+ },
+ .{
+ .base = "https://example/app/dir/#/foo/bar",
+ .path = "../api/users/login",
+ .expected = "https://example/app/api/users/login",
+ },
+ .{
+ .base = "https://example/app/page?next=/foo/bar",
+ .path = "?q=/api/users/login",
+ .expected = "https://example/app/page?q=/api/users/login",
+ },
+ .{
+ .base = "https://example/app/page#/foo/bar",
+ .path = "#/api/users/login",
+ .expected = "https://example/app/page#/api/users/login",
+ },
.{
.base = "https://example/xyz/abc/123",
.path = "/something.js",
diff --git a/src/browser/tests/net/fetch_hash_route.html b/src/browser/tests/net/fetch_hash_route.html
new file mode 100644
index 00000000..8a794550
--- /dev/null
+++ b/src/browser/tests/net/fetch_hash_route.html
@@ -0,0 +1,28 @@
+
+
+
+
diff --git a/src/browser/webapi/net/Fetch.zig b/src/browser/webapi/net/Fetch.zig
index 1f69ef0e..74b3351c 100644
--- a/src/browser/webapi/net/Fetch.zig
+++ b/src/browser/webapi/net/Fetch.zig
@@ -270,4 +270,5 @@ fn httpShutdownCallback(ctx: *anyopaque) void {
const testing = @import("../../../testing.zig");
test "WebApi: fetch" {
try testing.htmlRunner("net/fetch.html", .{});
+ try testing.htmlRunner("net/fetch_hash_route.html", .{});
}