Ignore Range on requests other than GET and HEAD

RFC 9110 14.2 defines range handling only for GET, and a server must
ignore a Range header on any other method. The server parsed it on
every method, so a POST with a Range got a 206 slice of the handler's
response, or a 416 when the Range was malformed. Range is now parsed
only for GET and HEAD; other methods get the whole response, and a
handler can still read the header itself.
This commit is contained in:
yhirose committed 2026-10-22 07:31:50 -04:00
1 parent b83b385ed4
commit 32a0ca8b35
2 files changed
+28 -1

No files matched your search

+3 -1
View File
@@ -15202,7 +15202,9 @@ Server::process_request(Stream &strm, const std::string &remote_addr,
}
}
if (req.has_header("Range")) {
// RFC 9110 14.2: range handling is defined only for GET (and so for HEAD)
if ((req.method == "GET" || req.method == "HEAD") &&
req.has_header("Range")) {
const auto &range_header_value = req.get_header_value("Range");
if (!detail::parse_range_header(range_header_value, req.ranges)) {
connection_closed = true;
+25
View File
@@ -2742,6 +2742,31 @@ TEST(RangeTest, FromHTTPBin_Online) {
}
}
TEST(RangeTest, IgnoredForPost) {
Server svr;
svr.Post("/", [](const Request &, Response &res) {
res.set_content("abcdefg", "text/plain");
});
auto port = svr.bind_to_any_port(HOST);
ASSERT_GT(port, 0);
thread t = thread([&] { svr.listen_after_bind(); });
auto se = detail::scope_exit([&] {
svr.stop();
t.join();
ASSERT_FALSE(svr.is_running());
});
svr.wait_until_ready();
Client cli(HOST, port);
for (auto range : {"bytes=1-2", "bytes=x"}) {
auto res = cli.Post("/", Headers{{"Range", range}});
ASSERT_TRUE(res) << range << ": " << to_string(res.error());
EXPECT_EQ(StatusCode::OK_200, res->status) << range;
EXPECT_EQ("abcdefg", res->body) << range;
}
}
TEST(GetAddrInfoDanglingRefTest, LongTimeout) {
auto host = "unresolvableaddress.local";
auto path = std::string{"/"};