mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-03-30 17:18:57 +00:00
Compare commits
4 Commits
fix/cdp-cr
...
url/resolv
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ca76575c2a | ||
|
|
49cef740b2 | ||
|
|
4d812f1e74 | ||
|
|
3ee1da0ac1 |
@@ -77,6 +77,41 @@ pub fn resolve(allocator: Allocator, base: [:0]const u8, path: anytype, comptime
|
|||||||
return processResolved(allocator, result, opts);
|
return processResolved(allocator, result, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (path.len >= 4) { // Minimum: "ws:x"
|
||||||
|
if (std.mem.indexOfScalar(u8, path[0..@min(path.len, 6)], ':')) |pos| {
|
||||||
|
// we know this isn't a complete URL, else the very first check in
|
||||||
|
// this function would have handled it.
|
||||||
|
const possible_special_protocol = path[0..pos];
|
||||||
|
const special_schemes = [_][]const u8{ "https", "http", "ws", "wss", "file", "ftp" };
|
||||||
|
for (special_schemes) |special_scheme| {
|
||||||
|
if (std.ascii.eqlIgnoreCase(possible_special_protocol, special_scheme)) {
|
||||||
|
const rest = path[pos + 1 ..];
|
||||||
|
|
||||||
|
// Check if base has the same scheme
|
||||||
|
const base_scheme_end = std.mem.indexOf(u8, base, "://") orelse 0;
|
||||||
|
if (base_scheme_end > 0 and std.ascii.eqlIgnoreCase(base[0..base_scheme_end], special_scheme)) {
|
||||||
|
// Same scheme - strip it and resolve rest as relative
|
||||||
|
return resolve(allocator, base, rest, opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Different scheme - construct absolute URL
|
||||||
|
// Skip any leading slashes in rest
|
||||||
|
var rest_start: usize = 0;
|
||||||
|
while (rest_start < rest.len and (rest[rest_start] == '/' or rest[rest_start] == '\\')) {
|
||||||
|
rest_start += 1;
|
||||||
|
}
|
||||||
|
const rest_trimmed = rest[rest_start..];
|
||||||
|
|
||||||
|
// file: scheme needs empty host (triple slash)
|
||||||
|
const separator = if (std.mem.eql(u8, special_scheme, "file")) ":///" else "://";
|
||||||
|
const normalized = try std.mem.joinZ(allocator, "", &.{ special_scheme, separator, rest_trimmed });
|
||||||
|
return resolve(allocator, "", normalized, opts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Don't know what this is, just try to resolve it through our normal logic
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const scheme_end = std.mem.indexOf(u8, base, "://");
|
const scheme_end = std.mem.indexOf(u8, base, "://");
|
||||||
const authority_start = if (scheme_end) |end| end + 3 else 0;
|
const authority_start = if (scheme_end) |end| end + 3 else 0;
|
||||||
const path_start = std.mem.indexOfScalarPos(u8, base, authority_start, '/') orelse base.len;
|
const path_start = std.mem.indexOfScalarPos(u8, base, authority_start, '/') orelse base.len;
|
||||||
@@ -1570,3 +1605,84 @@ test "URL: getOrigin" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "URL: resolve path scheme" {
|
||||||
|
const Case = struct {
|
||||||
|
base: [:0]const u8,
|
||||||
|
path: [:0]const u8,
|
||||||
|
expected: [:0]const u8,
|
||||||
|
};
|
||||||
|
|
||||||
|
const cases = [_]Case{
|
||||||
|
.{
|
||||||
|
.base = "https://www.example.com/example",
|
||||||
|
.path = "https:/about",
|
||||||
|
.expected = "https://www.example.com/about",
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.base = "https://www.example.com/example",
|
||||||
|
.path = "https:about",
|
||||||
|
.expected = "https://www.example.com/about",
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.base = "https://www.example.com/example",
|
||||||
|
.path = "https://about",
|
||||||
|
.expected = "https://about",
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.base = "https://www.example.com/example",
|
||||||
|
.path = "http:about",
|
||||||
|
.expected = "http://about",
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.base = "https://www.example.com/example",
|
||||||
|
.path = "http:/about",
|
||||||
|
.expected = "http://about",
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.base = "https://www.example.com/example",
|
||||||
|
.path = "http://about",
|
||||||
|
.expected = "http://about",
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.base = "https://site/",
|
||||||
|
.path = "https://path",
|
||||||
|
.expected = "https://path",
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.base = "http://localhost/",
|
||||||
|
.path = "data:test",
|
||||||
|
.expected = "data:test",
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.base = "https://www.example.com/example",
|
||||||
|
.path = "ws://about",
|
||||||
|
.expected = "ws://about",
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.base = "https://www.example.com/example",
|
||||||
|
.path = "wss://about",
|
||||||
|
.expected = "wss://about",
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.base = "https://www.example.com/example",
|
||||||
|
.path = "ftp://about",
|
||||||
|
.expected = "ftp://about",
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.base = "https://www.example.com/example",
|
||||||
|
.path = "file://path/to/file",
|
||||||
|
.expected = "file://path/to/file",
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.base = "https://www.example.com/example",
|
||||||
|
.path = "file:/path/to/file",
|
||||||
|
.expected = "file:///path/to/file",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
for (cases) |case| {
|
||||||
|
const result = try resolve(testing.arena_allocator, case.base, case.path, .{});
|
||||||
|
try testing.expectString(case.expected, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user