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