mirror of
https://github.com/yhirose/cpp-httplib.git
synced 2026-10-23 11:54:42 +00:00
Merge pull request #2504 from emreay-/skip-drain-on-closing-connection
Skip request body drain when connection will close
This commit is contained in:
2 files changed
+60
-5
No files matched your search
@@ -12772,13 +12772,19 @@ Server::process_request(Stream &strm, const std::string &remote_addr,
|
|||||||
|
|
||||||
// Drain any unconsumed framed body to prevent request smuggling on
|
// Drain any unconsumed framed body to prevent request smuggling on
|
||||||
// keep-alive. Without framing there is no body to drain — reading would
|
// keep-alive. Without framing there is no body to drain — reading would
|
||||||
// consume the next request (issue #2450).
|
// consume the next request (issue #2450). If the response has committed the
|
||||||
|
// connection to close, there is no next request to protect.
|
||||||
if (!req.body_consumed_ && detail::has_framed_body(req)) {
|
if (!req.body_consumed_ && detail::has_framed_body(req)) {
|
||||||
int dummy_status;
|
if (res.get_header_value("Connection") == "close") {
|
||||||
if (!detail::read_content(
|
|
||||||
strm, req, payload_max_length_, dummy_status, nullptr,
|
|
||||||
[](const char *, size_t, size_t, size_t) { return true; }, false)) {
|
|
||||||
connection_closed = true;
|
connection_closed = true;
|
||||||
|
} else {
|
||||||
|
int dummy_status;
|
||||||
|
if (!detail::read_content(
|
||||||
|
strm, req, payload_max_length_, dummy_status, nullptr,
|
||||||
|
[](const char *, size_t, size_t, size_t) { return true; },
|
||||||
|
false)) {
|
||||||
|
connection_closed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20039,6 +20039,55 @@ TEST(KeepAliveTest, DeleteWithoutContentLengthDoesNotEatNextRequest) {
|
|||||||
EXPECT_EQ(2, delete_count.load());
|
EXPECT_EQ(2, delete_count.load());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(KeepAliveTest, UnconsumedChunkedBodyIsNotDrainedWhenResponseCloses) {
|
||||||
|
Server svr;
|
||||||
|
svr.Post("/ingest", [&](const Request &, Response &res,
|
||||||
|
const ContentReader &content_reader) {
|
||||||
|
auto consumed = content_reader([](const char *, size_t) { return false; });
|
||||||
|
EXPECT_FALSE(consumed);
|
||||||
|
res.status = StatusCode::Conflict_409;
|
||||||
|
res.set_header("Connection", "close");
|
||||||
|
});
|
||||||
|
|
||||||
|
auto port = svr.bind_to_any_port(HOST);
|
||||||
|
thread t = thread([&] { svr.listen_after_bind(); });
|
||||||
|
auto se = detail::scope_exit([&] {
|
||||||
|
svr.stop();
|
||||||
|
t.join();
|
||||||
|
});
|
||||||
|
svr.wait_until_ready();
|
||||||
|
|
||||||
|
auto error = Error::Success;
|
||||||
|
auto sock = detail::create_client_socket(
|
||||||
|
HOST, "", port, AF_UNSPEC, false, false, nullptr,
|
||||||
|
/*connection_timeout_sec=*/2, 0,
|
||||||
|
/*read_timeout_sec=*/1, 0,
|
||||||
|
/*write_timeout_sec=*/2, 0, std::string(), error);
|
||||||
|
ASSERT_NE(INVALID_SOCKET, sock);
|
||||||
|
auto sock_se = detail::scope_exit([&] { detail::close_socket(sock); });
|
||||||
|
|
||||||
|
std::string request = "POST /ingest HTTP/1.1\r\n"
|
||||||
|
"Host: localhost\r\n"
|
||||||
|
"Transfer-Encoding: chunked\r\n"
|
||||||
|
"\r\n"
|
||||||
|
"4\r\n"
|
||||||
|
"data\r\n";
|
||||||
|
auto sent = send(sock, request.data(), request.size(), 0);
|
||||||
|
ASSERT_EQ(static_cast<ssize_t>(request.size()), sent);
|
||||||
|
|
||||||
|
std::string response;
|
||||||
|
ssize_t received = 0;
|
||||||
|
do {
|
||||||
|
char buf[4096];
|
||||||
|
received = recv(sock, buf, sizeof(buf), 0);
|
||||||
|
if (received > 0) { response.append(buf, static_cast<size_t>(received)); }
|
||||||
|
} while (received > 0);
|
||||||
|
|
||||||
|
EXPECT_NE(std::string::npos, response.find("HTTP/1.1 409 Conflict"));
|
||||||
|
EXPECT_NE(std::string::npos, response.find("Connection: close"));
|
||||||
|
EXPECT_EQ(0, received);
|
||||||
|
}
|
||||||
|
|
||||||
namespace no_proxy_test {
|
namespace no_proxy_test {
|
||||||
|
|
||||||
// Server bound to 127.0.0.1:<dynamic>, listen thread spawned by listen(),
|
// Server bound to 127.0.0.1:<dynamic>, listen thread spawned by listen(),
|
||||||
|
|||||||
Reference in new issue
Block a user