Skip to content

Commit 8a9ef58

Browse files
committed
fix single slash url resolving issue
1 parent 1613345 commit 8a9ef58

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
@@ -204,6 +204,44 @@ pub const Session = struct {
204204
}
205205
};
206206

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

599637
// if a base path is given, we resolve src using base.
600638
if (base) |_base| {
601-
const dir = std.fs.path.dirname(_base);
602-
if (dir) |_dir| {
603-
res_src = try std.fs.path.resolve(arena, &.{ _dir, src });
604-
}
639+
res_src = try stitchUrl(arena, src, _base);
605640
}
641+
606642
var origin_url = &self.url;
607643
const url = try origin_url.resolve(arena, res_src);
608644

@@ -872,3 +908,33 @@ test "Browser" {
872908
.{ "new Intl.DateTimeFormat()", "[object Intl.DateTimeFormat]" },
873909
}, .{});
874910
}
911+
912+
test "Stitching Base & Src URLs (Basic)" {
913+
const allocator = testing.allocator;
914+
915+
const base = "https://www.google.com/xyz/abc/123";
916+
const src = "something.js";
917+
const result = try stitchUrl(allocator, src, base);
918+
defer allocator.free(result);
919+
try testing.expectString("https://www.google.com/xyz/abc/something.js", result);
920+
}
921+
922+
test "Stitching Base & Src URLs (Just Ending Slash)" {
923+
const allocator = testing.allocator;
924+
925+
const base = "https://www.google.com/";
926+
const src = "something.js";
927+
const result = try stitchUrl(allocator, src, base);
928+
defer allocator.free(result);
929+
try testing.expectString("https://www.google.com/something.js", result);
930+
}
931+
932+
test "Stitching Base & Src URLs (No Ending Slash)" {
933+
const allocator = testing.allocator;
934+
935+
const base = "https://www.google.com";
936+
const src = "something.js";
937+
const result = try stitchUrl(allocator, src, base);
938+
defer allocator.free(result);
939+
try testing.expectString("https://www.google.com/something.js", result);
940+
}

0 commit comments

Comments
 (0)