yhirose před 2 týdny
rodič
revize
1a9552c4b0
2 změnil soubory, kde provedl 52 přidání a 2 odebrání
  1. 5 2
      httplib.h
  2. 47 0
      test/test.cc

+ 5 - 2
httplib.h

@@ -11191,7 +11191,8 @@ 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; }
+  auto write_request_success =
+      write_request(strm, req, close_connection, error);
 
 #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
   if (is_ssl()) {
@@ -11209,11 +11210,13 @@ inline bool ClientImpl::process_request(Stream &strm, Request &req,
   // Receive response and headers
   if (!read_response_line(strm, req, res) ||
       !detail::read_headers(strm, res.headers)) {
-    error = Error::Read;
+    if (write_request_success) { error = Error::Read; }
     output_error_log(error, &req);
     return false;
   }
 
+  if (!write_request_success) { return false; }
+
   // Body
   if ((res.status != StatusCode::NoContent_204) && req.method != "HEAD" &&
       req.method != "CONNECT") {

+ 47 - 0
test/test.cc

@@ -6567,6 +6567,53 @@ TEST_F(ServerTest, PreCompressionLoggingOnlyPreLogger) {
   EXPECT_EQ(test_content, pre_compression_body);
 }
 
+TEST_F(ServerTest, SendLargeBodyAfterRequestLineError) {
+  {
+    Request req;
+    req.method = "POST";
+    req.path = "/post-large?q=" + LONG_QUERY_VALUE;
+    req.body = LARGE_DATA;
+
+    Response res;
+    auto error = Error::Success;
+
+    auto start = std::chrono::high_resolution_clock::now();
+    cli_.set_keep_alive(true);
+    auto ret = cli_.send(req, res, error);
+    auto end = std::chrono::high_resolution_clock::now();
+
+    auto elapsed =
+        std::chrono::duration_cast<std::chrono::milliseconds>(end - start)
+            .count();
+
+    EXPECT_FALSE(ret);
+    EXPECT_EQ(StatusCode::UriTooLong_414, res.status);
+    EXPECT_EQ("close", res.get_header_value("Connection"));
+    EXPECT_FALSE(cli_.is_socket_open());
+    EXPECT_LE(elapsed, 200);
+  }
+
+  {
+    // Send an extra GET request to ensure error recovery without hanging
+    Request req;
+    req.method = "GET";
+    req.path = "/hi";
+
+    auto start = std::chrono::high_resolution_clock::now();
+    auto res = cli_.send(req);
+    auto end = std::chrono::high_resolution_clock::now();
+
+    auto elapsed =
+        std::chrono::duration_cast<std::chrono::milliseconds>(end - start)
+            .count();
+
+    ASSERT_TRUE(res);
+    EXPECT_EQ(StatusCode::OK_200, res->status);
+    EXPECT_EQ("Hello World!", res->body);
+    EXPECT_LE(elapsed, 100);
+  }
+}
+
 TEST(ZstdDecompressor, ChunkedDecompression) {
   std::string data;
   for (size_t i = 0; i < 32 * 1024; ++i) {