mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-10-29 23:23:28 +00:00
handling relative base URLs
This commit is contained in:
@@ -205,44 +205,6 @@ pub const Session = struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Properly stitches two URLs together.
|
|
||||||
//
|
|
||||||
// For URLs with a path, it will replace the last entry with the src.
|
|
||||||
// For URLs without a path, it will add src as the path.
|
|
||||||
fn stitchUrl(allocator: std.mem.Allocator, src: []const u8, base: []const u8) ![]const u8 {
|
|
||||||
// Traversing until the path
|
|
||||||
var slash_iter = std.mem.splitScalar(u8, base, '/');
|
|
||||||
_ = slash_iter.next();
|
|
||||||
_ = slash_iter.next();
|
|
||||||
_ = slash_iter.next();
|
|
||||||
|
|
||||||
if (slash_iter.index) |path_index| {
|
|
||||||
// Remove final slash from pathless base slice.
|
|
||||||
const pathless_base = base[0 .. path_index - 1];
|
|
||||||
const path = slash_iter.rest();
|
|
||||||
|
|
||||||
if (path.len > 0) {
|
|
||||||
var split_halves = std.mem.splitBackwardsScalar(u8, path, '/');
|
|
||||||
_ = split_halves.first();
|
|
||||||
const stripped_path = split_halves.rest();
|
|
||||||
|
|
||||||
if (stripped_path.len > 0) {
|
|
||||||
// Multi path entry
|
|
||||||
return try std.fmt.allocPrint(allocator, "{s}/{s}/{s}", .{ pathless_base, stripped_path, src });
|
|
||||||
} else {
|
|
||||||
// Single path entry
|
|
||||||
return try std.fmt.allocPrint(allocator, "{s}/{s}", .{ pathless_base, src });
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Slash at the end case
|
|
||||||
return try std.fmt.allocPrint(allocator, "{s}/{s}", .{ pathless_base, src });
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// No path case
|
|
||||||
return try std.fmt.allocPrint(allocator, "{s}/{s}", .{ base, src });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Page navigates to an url.
|
// Page navigates to an url.
|
||||||
// You can navigates multiple urls with the same page, but you have to call
|
// You can navigates multiple urls with the same page, but you have to call
|
||||||
// end() to stop the previous navigation before starting a new one.
|
// end() to stop the previous navigation before starting a new one.
|
||||||
@@ -637,7 +599,7 @@ pub const Page = struct {
|
|||||||
|
|
||||||
// if a base path is given, we resolve src using base.
|
// if a base path is given, we resolve src using base.
|
||||||
if (base) |_base| {
|
if (base) |_base| {
|
||||||
res_src = try stitchUrl(arena, src, _base);
|
res_src = try URL.stitch(arena, src, _base);
|
||||||
}
|
}
|
||||||
|
|
||||||
var origin_url = &self.url;
|
var origin_url = &self.url;
|
||||||
@@ -934,33 +896,3 @@ test "Browser" {
|
|||||||
.{ "new Intl.DateTimeFormat()", "[object Intl.DateTimeFormat]" },
|
.{ "new Intl.DateTimeFormat()", "[object Intl.DateTimeFormat]" },
|
||||||
}, .{});
|
}, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
test "Stitching Base & Src URLs (Basic)" {
|
|
||||||
const allocator = testing.allocator;
|
|
||||||
|
|
||||||
const base = "https://www.google.com/xyz/abc/123";
|
|
||||||
const src = "something.js";
|
|
||||||
const result = try stitchUrl(allocator, src, base);
|
|
||||||
defer allocator.free(result);
|
|
||||||
try testing.expectString("https://www.google.com/xyz/abc/something.js", result);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "Stitching Base & Src URLs (Just Ending Slash)" {
|
|
||||||
const allocator = testing.allocator;
|
|
||||||
|
|
||||||
const base = "https://www.google.com/";
|
|
||||||
const src = "something.js";
|
|
||||||
const result = try stitchUrl(allocator, src, base);
|
|
||||||
defer allocator.free(result);
|
|
||||||
try testing.expectString("https://www.google.com/something.js", result);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "Stitching Base & Src URLs (No Ending Slash)" {
|
|
||||||
const allocator = testing.allocator;
|
|
||||||
|
|
||||||
const base = "https://www.google.com";
|
|
||||||
const src = "something.js";
|
|
||||||
const result = try stitchUrl(allocator, src, base);
|
|
||||||
defer allocator.free(result);
|
|
||||||
try testing.expectString("https://www.google.com/something.js", result);
|
|
||||||
}
|
|
||||||
|
|||||||
71
src/url.zig
71
src/url.zig
@@ -81,6 +81,35 @@ pub const URL = struct {
|
|||||||
pub fn toWebApi(self: *const URL, allocator: Allocator) !WebApiURL {
|
pub fn toWebApi(self: *const URL, allocator: Allocator) !WebApiURL {
|
||||||
return WebApiURL.init(allocator, self.uri);
|
return WebApiURL.init(allocator, self.uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Properly stitches two URL fragments together.
|
||||||
|
///
|
||||||
|
/// For URLs with a path, it will replace the last entry with the src.
|
||||||
|
/// For URLs without a path, it will add src as the path.
|
||||||
|
pub fn stitch(allocator: std.mem.Allocator, src: []const u8, base: []const u8) ![]const u8 {
|
||||||
|
if (base.len == 0) {
|
||||||
|
return src;
|
||||||
|
}
|
||||||
|
|
||||||
|
const protocol_end: usize = blk: {
|
||||||
|
if (std.mem.indexOf(u8, base, "://")) |protocol_index| {
|
||||||
|
break :blk protocol_index + 3;
|
||||||
|
} else {
|
||||||
|
break :blk 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (std.mem.lastIndexOfScalar(u8, base[protocol_end..], '/')) |index| {
|
||||||
|
const last_slash_pos = index + protocol_end;
|
||||||
|
if (last_slash_pos == base.len - 1) {
|
||||||
|
return std.fmt.allocPrint(allocator, "{s}{s}", .{ base, src });
|
||||||
|
} else {
|
||||||
|
return std.fmt.allocPrint(allocator, "{s}/{s}", .{ base[0..last_slash_pos], src });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return std.fmt.allocPrint(allocator, "{s}/{s}", .{ base, src });
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
test "Url resolve size" {
|
test "Url resolve size" {
|
||||||
@@ -98,3 +127,45 @@ test "Url resolve size" {
|
|||||||
try std.testing.expectEqual(out_url.raw[25], '/');
|
try std.testing.expectEqual(out_url.raw[25], '/');
|
||||||
try std.testing.expectEqualStrings(out_url.raw[26..], &url_string);
|
try std.testing.expectEqualStrings(out_url.raw[26..], &url_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const testing = @import("testing.zig");
|
||||||
|
|
||||||
|
test "URL: Stitching Base & Src URLs (Basic)" {
|
||||||
|
const allocator = testing.allocator;
|
||||||
|
|
||||||
|
const base = "https://www.google.com/xyz/abc/123";
|
||||||
|
const src = "something.js";
|
||||||
|
const result = try URL.stitch(allocator, src, base);
|
||||||
|
defer allocator.free(result);
|
||||||
|
try testing.expectString("https://www.google.com/xyz/abc/something.js", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "URL: Stitching Base & Src URLs (Just Ending Slash)" {
|
||||||
|
const allocator = testing.allocator;
|
||||||
|
|
||||||
|
const base = "https://www.google.com/";
|
||||||
|
const src = "something.js";
|
||||||
|
const result = try URL.stitch(allocator, src, base);
|
||||||
|
defer allocator.free(result);
|
||||||
|
try testing.expectString("https://www.google.com/something.js", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "URL: Stitching Base & Src URLs (No Ending Slash)" {
|
||||||
|
const allocator = testing.allocator;
|
||||||
|
|
||||||
|
const base = "https://www.google.com";
|
||||||
|
const src = "something.js";
|
||||||
|
const result = try URL.stitch(allocator, src, base);
|
||||||
|
defer allocator.free(result);
|
||||||
|
try testing.expectString("https://www.google.com/something.js", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "URL: Stiching Base & Src URLs (Both Local)" {
|
||||||
|
const allocator = testing.allocator;
|
||||||
|
|
||||||
|
const base = "./abcdef/123.js";
|
||||||
|
const src = "something.js";
|
||||||
|
const result = try URL.stitch(allocator, src, base);
|
||||||
|
defer allocator.free(result);
|
||||||
|
try testing.expectString("./abcdef/something.js", result);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user