page: replay POST method/body/header on Page.reload

doReload built a NavigateOpts with only url + kind=.reload; method/body/header
defaulted to GET/null/null, so any prior POST navigation regressed to a GET
on reload. The HTML reload navigation re-fetches the document that produced
the current entry, and Chrome replays the same HTTP request that loaded the
page (including method, body, and Content-Type) — Lightpanda dropped all
three.

Retain the prior request body and content-type header in Frame.NavigatedOpts
(duped into the frame arena), and have doReload capture them into the CDP
command's arena before replacePage() frees the old frame. The reload's
frame.navigate call carries the replayed method/body/header so the request
the page was loaded with is the request that runs again.

Closes #2258
This commit is contained in:
Navid EMAD
2026-04-27 06:28:58 +02:00
parent a578f4d6ad
commit ea6b228f9d
3 changed files with 90 additions and 1 deletions

View File

@@ -636,6 +636,19 @@ fn testHTTPHandler(req: *std.http.Server.Request) !void {
});
}
if (std.mem.eql(u8, path, "/echo_method")) {
// Echo the request method back as HTML so tests can assert on what
// method the navigation used. Used by the Page.reload-replays-POST test.
const method_name = @tagName(req.head.method);
var html_buf: [128]u8 = undefined;
const html = try std.fmt.bufPrint(&html_buf, "<html><body>method={s}</body></html>", .{method_name});
return req.respond(html, .{
.extra_headers = &.{
.{ .name = "Content-Type", .value = "text/html; charset=utf-8" },
},
});
}
if (std.mem.startsWith(u8, path, "/src/browser/tests/")) {
// strip off leading / so that it's relative to CWD
return TestHTTPServer.sendFile(req, path[1..]);