Skip to content

Commit f10bee8

Browse files
committed
fix single slash url resolving issue
1 parent eadf188 commit f10bee8

File tree

1 file changed

+70
-4
lines changed

1 file changed

+70
-4
lines changed

src/browser/browser.zig

Lines changed: 70 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,44 @@ pub const Session = struct {
205205
}
206206
};
207207

208+
// Properly stitches two URLs together.
209+
//
210+
// For URLs with a path, it will replace the last entry with the src.
211+
// For URLs without a path, it will add src as the path.
212+
fn stitchUrl(allocator: std.mem.Allocator, src: []const u8, base: []const u8) ![]const u8 {
213+
// Traversing until the path
214+
var slash_iter = std.mem.splitScalar(u8, base, '/');
215+
_ = slash_iter.next();
216+
_ = slash_iter.next();
217+
_ = slash_iter.next();
218+
219+
if (slash_iter.index) |path_index| {
220+
// Remove final slash from pathless base slice.
221+
const pathless_base = base[0 .. path_index - 1];
222+
const path = slash_iter.rest();
223+
224+
if (path.len > 0) {
225+
var split_halves = std.mem.splitBackwardsScalar(u8, path, '/');
226+
_ = split_halves.first();
227+
const stripped_path = split_halves.rest();
228+
229+
if (stripped_path.len > 0) {
230+
// Multi path entry
231+
return try std.fmt.allocPrint(allocator, "{s}/{s}/{s}", .{ pathless_base, stripped_path, src });
232+
} else {
233+
// Single path entry
234+
return try std.fmt.allocPrint(allocator, "{s}/{s}", .{ pathless_base, src });
235+
}
236+
} else {
237+
// Slash at the end case
238+
return try std.fmt.allocPrint(allocator, "{s}/{s}", .{ pathless_base, src });
239+
}
240+
} else {
241+
// No path case
242+
return try std.fmt.allocPrint(allocator, "{s}/{s}", .{ base, src });
243+
}
244+
}
245+
208246
// Page navigates to an url.
209247
// You can navigates multiple urls with the same page, but you have to call
210248
// end() to stop the previous navigation before starting a new one.
@@ -599,11 +637,9 @@ pub const Page = struct {
599637

600638
// if a base path is given, we resolve src using base.
601639
if (base) |_base| {
602-
const dir = std.fs.path.dirname(_base);
603-
if (dir) |_dir| {
604-
res_src = try std.fs.path.resolve(arena, &.{ _dir, src });
605-
}
640+
res_src = try stitchUrl(arena, src, _base);
606641
}
642+
607643
var origin_url = &self.url;
608644
const url = try origin_url.resolve(arena, res_src);
609645

@@ -898,3 +934,33 @@ test "Browser" {
898934
.{ "new Intl.DateTimeFormat()", "[object Intl.DateTimeFormat]" },
899935
}, .{});
900936
}
937+
938+
test "Stitching Base & Src URLs (Basic)" {
939+
const allocator = testing.allocator;
940+
941+
const base = "https://www.google.com/xyz/abc/123";
942+
const src = "something.js";
943+
const result = try stitchUrl(allocator, src, base);
944+
defer allocator.free(result);
945+
try testing.expectString("https://www.google.com/xyz/abc/something.js", result);
946+
}
947+
948+
test "Stitching Base & Src URLs (Just Ending Slash)" {
949+
const allocator = testing.allocator;
950+
951+
const base = "https://www.google.com/";
952+
const src = "something.js";
953+
const result = try stitchUrl(allocator, src, base);
954+
defer allocator.free(result);
955+
try testing.expectString("https://www.google.com/something.js", result);
956+
}
957+
958+
test "Stitching Base & Src URLs (No Ending Slash)" {
959+
const allocator = testing.allocator;
960+
961+
const base = "https://www.google.com";
962+
const src = "something.js";
963+
const result = try stitchUrl(allocator, src, base);
964+
defer allocator.free(result);
965+
try testing.expectString("https://www.google.com/something.js", result);
966+
}

0 commit comments

Comments
 (0)