Skip to content

Commit ff9fa7d

Browse files
committed
handling relative base URLs
1 parent 8a9ef58 commit ff9fa7d

File tree

2 files changed

+72
-69
lines changed

2 files changed

+72
-69
lines changed

src/browser/browser.zig

Lines changed: 1 addition & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -204,44 +204,6 @@ 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-
245207
// Page navigates to an url.
246208
// You can navigates multiple urls with the same page, but you have to call
247209
// end() to stop the previous navigation before starting a new one.
@@ -636,7 +598,7 @@ pub const Page = struct {
636598

637599
// if a base path is given, we resolve src using base.
638600
if (base) |_base| {
639-
res_src = try stitchUrl(arena, src, _base);
601+
res_src = try URL.stitch(arena, src, _base);
640602
}
641603

642604
var origin_url = &self.url;
@@ -908,33 +870,3 @@ test "Browser" {
908870
.{ "new Intl.DateTimeFormat()", "[object Intl.DateTimeFormat]" },
909871
}, .{});
910872
}
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-
}

src/url.zig

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,4 +81,75 @@ pub const URL = struct {
8181
pub fn toWebApi(self: *const URL, allocator: Allocator) !WebApiURL {
8282
return WebApiURL.init(allocator, self.uri);
8383
}
84+
85+
/// Properly stitches two URL fragments together.
86+
///
87+
/// For URLs with a path, it will replace the last entry with the src.
88+
/// For URLs without a path, it will add src as the path.
89+
pub fn stitch(allocator: std.mem.Allocator, src: []const u8, base: []const u8) ![]const u8 {
90+
if (base.len == 0) {
91+
return src;
92+
}
93+
94+
const protocol_end: usize = blk: {
95+
if (std.mem.indexOf(u8, base, "://")) |protocol_index| {
96+
break :blk protocol_index + 3;
97+
} else {
98+
break :blk 0;
99+
}
100+
};
101+
102+
if (std.mem.lastIndexOfScalar(u8, base[protocol_end..], '/')) |index| {
103+
const last_slash_pos = index + protocol_end;
104+
if (last_slash_pos == base.len - 1) {
105+
return std.fmt.allocPrint(allocator, "{s}{s}", .{ base, src });
106+
} else {
107+
return std.fmt.allocPrint(allocator, "{s}/{s}", .{ base[0..last_slash_pos], src });
108+
}
109+
} else {
110+
return std.fmt.allocPrint(allocator, "{s}/{s}", .{ base, src });
111+
}
112+
}
84113
};
114+
115+
const testing = @import("testing.zig");
116+
117+
test "URL: Stitching Base & Src URLs (Basic)" {
118+
const allocator = testing.allocator;
119+
120+
const base = "https://www.google.com/xyz/abc/123";
121+
const src = "something.js";
122+
const result = try URL.stitch(allocator, src, base);
123+
defer allocator.free(result);
124+
try testing.expectString("https://www.google.com/xyz/abc/something.js", result);
125+
}
126+
127+
test "URL: Stitching Base & Src URLs (Just Ending Slash)" {
128+
const allocator = testing.allocator;
129+
130+
const base = "https://www.google.com/";
131+
const src = "something.js";
132+
const result = try URL.stitch(allocator, src, base);
133+
defer allocator.free(result);
134+
try testing.expectString("https://www.google.com/something.js", result);
135+
}
136+
137+
test "URL: Stitching Base & Src URLs (No Ending Slash)" {
138+
const allocator = testing.allocator;
139+
140+
const base = "https://www.google.com";
141+
const src = "something.js";
142+
const result = try URL.stitch(allocator, src, base);
143+
defer allocator.free(result);
144+
try testing.expectString("https://www.google.com/something.js", result);
145+
}
146+
147+
test "URL: Stiching Base & Src URLs (Both Local)" {
148+
const allocator = testing.allocator;
149+
150+
const base = "./abcdef/123.js";
151+
const src = "something.js";
152+
const result = try URL.stitch(allocator, src, base);
153+
defer allocator.free(result);
154+
try testing.expectString("./abcdef/something.js", result);
155+
}

0 commit comments

Comments
 (0)