mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-06-11 01:25:53 -04:00
Merge pull request #2265 from navidemad/fix-a16-redirect-fragment-inherit
http: inherit request URL fragment across fragment-less redirect
This commit is contained in:
@@ -1572,7 +1572,19 @@ pub const Transfer = struct {
|
||||
}
|
||||
|
||||
const base_url = try conn.getEffectiveUrl();
|
||||
break :blk try URL.resolve(arena, std.mem.span(base_url), location.value, .{});
|
||||
const resolved = try URL.resolve(arena, std.mem.span(base_url), location.value, .{});
|
||||
|
||||
// RFC 7231 §7.1.2: if the Location value has no fragment, the redirect
|
||||
// inherits the fragment from the URI used to generate the request.
|
||||
// URL.resolve follows RFC 3986 §5.3, which drops the base fragment when
|
||||
// the relative ref has none, so we re-attach it here.
|
||||
if (URL.getHash(resolved).len == 0) {
|
||||
const original_hash = URL.getHash(transfer.url);
|
||||
if (original_hash.len != 0) {
|
||||
break :blk try std.mem.joinZ(arena, "", &.{ resolved, original_hash });
|
||||
}
|
||||
}
|
||||
break :blk resolved;
|
||||
};
|
||||
|
||||
try transfer.updateURL(url);
|
||||
|
||||
@@ -1003,6 +1003,60 @@ test "cdp.frame: reload" {
|
||||
}
|
||||
}
|
||||
|
||||
test "cdp.frame: navigate inherits original fragment across redirect" {
|
||||
// RFC 7231 §7.1.2: when a 3xx Location header has no fragment, the redirect
|
||||
// inherits the fragment of the request URL.
|
||||
var ctx = try testing.context();
|
||||
defer ctx.deinit();
|
||||
|
||||
var bc = try ctx.loadBrowserContext(.{ .id = "BID-9", .url = "hi.html", .target_id = "FID-000000000X".* });
|
||||
|
||||
{
|
||||
// Location: /redirect-target (no fragment) — must inherit #myfrag.
|
||||
try ctx.processMessage(.{
|
||||
.id = 40,
|
||||
.method = "Page.navigate",
|
||||
.params = .{ .url = "http://127.0.0.1:9582/redirect-no-fragment#myfrag" },
|
||||
});
|
||||
|
||||
var runner = try bc.session.runner(.{});
|
||||
try runner.wait(.{ .ms = 2000 });
|
||||
|
||||
const frame = bc.session.currentFrame() orelse unreachable;
|
||||
try testing.expectEqualSlices(u8, "http://127.0.0.1:9582/redirect-target#myfrag", frame.url);
|
||||
}
|
||||
|
||||
{
|
||||
// Location: /redirect-target#target_fragment — target's fragment wins.
|
||||
try ctx.processMessage(.{
|
||||
.id = 41,
|
||||
.method = "Page.navigate",
|
||||
.params = .{ .url = "http://127.0.0.1:9582/redirect-with-fragment#requested" },
|
||||
});
|
||||
|
||||
var runner = try bc.session.runner(.{});
|
||||
try runner.wait(.{ .ms = 2000 });
|
||||
|
||||
const frame = bc.session.currentFrame() orelse unreachable;
|
||||
try testing.expectEqualSlices(u8, "http://127.0.0.1:9582/redirect-target#target_fragment", frame.url);
|
||||
}
|
||||
|
||||
{
|
||||
// No fragment on either side — final URL has no fragment.
|
||||
try ctx.processMessage(.{
|
||||
.id = 42,
|
||||
.method = "Page.navigate",
|
||||
.params = .{ .url = "http://127.0.0.1:9582/redirect-no-fragment" },
|
||||
});
|
||||
|
||||
var runner = try bc.session.runner(.{});
|
||||
try runner.wait(.{ .ms = 2000 });
|
||||
|
||||
const frame = bc.session.currentFrame() orelse unreachable;
|
||||
try testing.expectEqualSlices(u8, "http://127.0.0.1:9582/redirect-target", frame.url);
|
||||
}
|
||||
}
|
||||
|
||||
test "cdp.frame: addScriptToEvaluateOnNewDocument" {
|
||||
var ctx = try testing.context();
|
||||
defer ctx.deinit();
|
||||
|
||||
@@ -610,6 +610,32 @@ fn testHTTPHandler(req: *std.http.Server.Request) !void {
|
||||
});
|
||||
}
|
||||
|
||||
if (std.mem.eql(u8, path, "/redirect-no-fragment")) {
|
||||
return req.respond("", .{
|
||||
.status = .found,
|
||||
.extra_headers = &.{
|
||||
.{ .name = "Location", .value = "/redirect-target" },
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (std.mem.eql(u8, path, "/redirect-target")) {
|
||||
return req.respond("<!DOCTYPE html><title>landed</title>", .{
|
||||
.extra_headers = &.{
|
||||
.{ .name = "Content-Type", .value = "text/html; charset=utf-8" },
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (std.mem.eql(u8, path, "/redirect-with-fragment")) {
|
||||
return req.respond("", .{
|
||||
.status = .found,
|
||||
.extra_headers = &.{
|
||||
.{ .name = "Location", .value = "/redirect-target#target_fragment" },
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (std.mem.eql(u8, path, "/xhr/404")) {
|
||||
return req.respond("Not Found", .{
|
||||
.status = .not_found,
|
||||
|
||||
Reference in New Issue
Block a user