Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions httplib.h
Original file line number Diff line number Diff line change
Expand Up @@ -7133,7 +7133,7 @@ inline ssize_t SocketStream::read(char *ptr, size_t size) {
}

inline ssize_t SocketStream::write(const char *ptr, size_t size) {
if (!wait_writable()) { return -1; }
if (!detail::is_socket_alive(sock_) || !wait_writable()) { return -1; }

#if defined(_WIN32) && !defined(_WIN64)
size =
Expand Down Expand Up @@ -9516,7 +9516,7 @@ inline bool ClientImpl::process_request(Stream &strm, Request &req,
Response &res, bool close_connection,
Error &error) {
// Send request
if (!write_request(strm, req, close_connection, error)) { return false; }
bool wrote = write_request(strm, req, close_connection, error);

#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
if (is_ssl()) {
Expand All @@ -9539,6 +9539,8 @@ inline bool ClientImpl::process_request(Stream &strm, Request &req,
return false;
}

if (!wrote) return false;

// Body
if ((res.status != StatusCode::NoContent_204) && req.method != "HEAD" &&
req.method != "CONNECT") {
Expand Down
43 changes: 43 additions & 0 deletions test/test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5898,6 +5898,49 @@ TEST_F(ServerTest, BadRequestLineCancelsKeepAlive) {
EXPECT_FALSE(cli_.is_socket_open());
}

TEST_F(ServerTest, SendLargeBodyAfterRequestLineError) {
Request post;
post.method = "POST";
post.path = "/post-large?q=" + LONG_QUERY_VALUE;
post.body = LARGE_DATA;

auto start = std::chrono::high_resolution_clock::now();

auto resPost = std::make_shared<Response>();
auto error = Error::Success;
cli_.set_keep_alive(true);
auto ret = cli_.send(post, *resPost, error);

auto end = std::chrono::high_resolution_clock::now();
auto elapsed =
std::chrono::duration_cast<std::chrono::milliseconds>(end - start)
.count();

EXPECT_FALSE(ret);
#ifndef _WIN32
EXPECT_EQ(StatusCode::UriTooLong_414, resPost->status);
EXPECT_EQ("close", resPost->get_header_value("Connection"));
#endif
EXPECT_FALSE(cli_.is_socket_open());
EXPECT_LE(elapsed, 200);

// Send an extra GET request to ensure error recovery without hanging
Request get;
get.method = "GET";
get.path = "/hi";

start = std::chrono::high_resolution_clock::now();
auto resGet = cli_.send(get);
end = std::chrono::high_resolution_clock::now();
elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start)
.count();

ASSERT_TRUE(resGet);
EXPECT_EQ(StatusCode::OK_200, resGet->status);
EXPECT_EQ("Hello World!", resGet->body);
EXPECT_LE(elapsed, 100);
}

TEST_F(ServerTest, StartTime) { auto res = cli_.Get("/test-start-time"); }

#ifdef CPPHTTPLIB_ZLIB_SUPPORT
Expand Down
Loading