mirror of
https://github.com/yhirose/cpp-httplib.git
synced 2026-10-19 11:19:36 +00:00
Close the connection after an ambiguous Transfer-Encoding
RFC 9112 6.1 has a server close the connection after answering a request with both Transfer-Encoding and Content-Length, or with Transfer-Encoding in HTTP/1.0. Close it, and send Connection: close whenever the connection closes after a response.
This commit is contained in:
1 parent
64bebd3b2b
commit
58957ae4da
2 files changed
+36
-4
No files matched your search
@@ -14761,6 +14761,13 @@ Server::process_request(Stream &strm, const std::string &remote_addr,
|
|||||||
return write_response(strm, close_connection, req, res);
|
return write_response(strm, close_connection, req, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RFC 9112 §6.1: answer a request that also has a Content-Length, or an
|
||||||
|
// HTTP/1.0 one, by its Transfer-Encoding, but close the connection after.
|
||||||
|
if (req.has_header("Transfer-Encoding") &&
|
||||||
|
(req.has_header("Content-Length") || req.version == "HTTP/1.0")) {
|
||||||
|
connection_closed = true;
|
||||||
|
}
|
||||||
|
|
||||||
// RFC 9112 §3.2: Reject more than one Host field line or an invalid Host
|
// RFC 9112 §3.2: Reject more than one Host field line or an invalid Host
|
||||||
// value, so that every recipient of the request sees the same authority.
|
// value, so that every recipient of the request sees the same authority.
|
||||||
if (req.get_header_value_count("Host") > 1 ||
|
if (req.get_header_value_count("Host") > 1 ||
|
||||||
@@ -14990,6 +14997,8 @@ Server::process_request(Stream &strm, const std::string &remote_addr,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
// The response says so when this connection closes after it.
|
||||||
|
auto close = close_connection || connection_closed;
|
||||||
auto ret = false;
|
auto ret = false;
|
||||||
if (routed) {
|
if (routed) {
|
||||||
if (res.status == -1) {
|
if (res.status == -1) {
|
||||||
@@ -15023,17 +15032,17 @@ Server::process_request(Stream &strm, const std::string &remote_addr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (file_open_error) {
|
if (file_open_error) {
|
||||||
ret = write_response(strm, close_connection, req, res);
|
ret = write_response(strm, close, req, res);
|
||||||
} else if (detail::range_error(req, res)) {
|
} else if (detail::range_error(req, res)) {
|
||||||
detail::clear_content(res);
|
detail::clear_content(res);
|
||||||
res.status = StatusCode::RangeNotSatisfiable_416;
|
res.status = StatusCode::RangeNotSatisfiable_416;
|
||||||
ret = write_response(strm, close_connection, req, res);
|
ret = write_response(strm, close, req, res);
|
||||||
} else {
|
} else {
|
||||||
ret = write_response_with_content(strm, close_connection, req, res);
|
ret = write_response_with_content(strm, close, req, res);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (res.status == -1) { res.status = StatusCode::NotFound_404; }
|
if (res.status == -1) { res.status = StatusCode::NotFound_404; }
|
||||||
ret = write_response(strm, close_connection, req, res);
|
ret = write_response(strm, close, req, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Drain any unconsumed framed body to prevent request smuggling on
|
// Drain any unconsumed framed body to prevent request smuggling on
|
||||||
|
|||||||
@@ -10836,6 +10836,29 @@ TEST(ServerRequestParsingTest, ExcessiveWhitespaceInUnparsableHeaderLine) {
|
|||||||
"\r\n");
|
"\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(ServerRequestParsingTest, AmbiguousTransferEncodingClosesConnection) {
|
||||||
|
// RFC 9112 §6.1
|
||||||
|
const char *requests[] = {
|
||||||
|
"PUT /put_hi HTTP/1.1\r\n"
|
||||||
|
"Content-Length: 0\r\n"
|
||||||
|
"Transfer-Encoding: chunked\r\n"
|
||||||
|
"\r\n"
|
||||||
|
"0\r\n\r\n",
|
||||||
|
"PUT /put_hi HTTP/1.0\r\n"
|
||||||
|
"Connection: keep-alive\r\n"
|
||||||
|
"Transfer-Encoding: chunked\r\n"
|
||||||
|
"\r\n"
|
||||||
|
"0\r\n\r\n",
|
||||||
|
};
|
||||||
|
|
||||||
|
for (auto request : requests) {
|
||||||
|
std::string out;
|
||||||
|
test_raw_request(request, &out);
|
||||||
|
EXPECT_EQ("HTTP/1.1 200 OK", out.substr(0, 15)) << request;
|
||||||
|
EXPECT_NE(std::string::npos, out.find("Connection: close")) << request;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TEST(ServerRequestParsingTest, InvalidFirstChunkLengthInRequest) {
|
TEST(ServerRequestParsingTest, InvalidFirstChunkLengthInRequest) {
|
||||||
std::string out;
|
std::string out;
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user