@@ -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