@@ -8434,3 +8434,114 @@ TEST(ClientInThreadTest, Issue2068) {
84348434 t.join ();
84358435 }
84368436}
8437+
8438+ template <typename S, typename C>
8439+ static void stream_handler_test (S &svr, C &cli) {
8440+ const auto delay = std::chrono::milliseconds{200 };
8441+ const auto timeout_us =
8442+ std::chrono::duration_cast<std::chrono::microseconds>(delay).count () / 2 ;
8443+
8444+ svr.Get (" /" , [delay](const Request &req, Response &res) {
8445+ // Request should contain limited default headers
8446+ EXPECT_EQ (req.has_header (" Host" ), true );
8447+ EXPECT_EQ (req.has_header (" User-Agent" ), true );
8448+ EXPECT_EQ (req.has_header (" Connection" ), true );
8449+ // Need connection to close at the end for test to succeed
8450+ EXPECT_EQ (req.get_header_value (" Connection" ), " close" );
8451+ // REMOTE_ADDR, REMOTE_PORT, LOCAL_ADDR, LOCAL_PORT = 4
8452+ EXPECT_EQ (req.headers .size (), (4 + 3 ));
8453+
8454+ res.set_stream_handler ([&](Stream &strm) -> bool {
8455+ char buf[16 ]{};
8456+ // Client shpuld time out first
8457+ std::this_thread::sleep_for (delay);
8458+ strm.write (buf, sizeof (buf));
8459+
8460+ // Synchronize with client and close connection
8461+ EXPECT_TRUE (strm.wait_readable ());
8462+
8463+ // Read to avoid RST on Windows
8464+ strm.read (buf, sizeof (buf));
8465+
8466+ return true ;
8467+ });
8468+ });
8469+ auto thread = std::thread ([&]() { svr.listen (HOST, PORT); });
8470+
8471+ auto se = detail::scope_exit ([&] {
8472+ svr.stop ();
8473+ thread.join ();
8474+ ASSERT_FALSE (svr.is_running ());
8475+ });
8476+
8477+ svr.wait_until_ready ();
8478+
8479+ Request req;
8480+ req.method = " GET" ;
8481+ req.path = " /" ;
8482+ req.response_handler = [](const Response &res) -> bool {
8483+ EXPECT_EQ (res.get_header_value (" Connection" ), " close" );
8484+ EXPECT_EQ (res.headers .size (), 1 );
8485+ return true ;
8486+ };
8487+ req.stream_handler = [delay](Stream &strm) -> bool {
8488+ char buf[16 ]{};
8489+ ssize_t n = 0 ;
8490+ // Buffer should be empty and first read should time out
8491+ EXPECT_FALSE (strm.is_readable ());
8492+ EXPECT_FALSE (strm.wait_readable ());
8493+
8494+ // Sever will send data soon
8495+ std::this_thread::sleep_for (delay);
8496+ EXPECT_TRUE (strm.wait_readable ());
8497+
8498+ n = strm.read (buf, sizeof (buf) / 2 );
8499+ EXPECT_EQ (sizeof (buf) / 2 , n);
8500+
8501+ // Server sent 16 bytes, we read 8; remainder should be buffered
8502+ EXPECT_TRUE (strm.is_readable ());
8503+
8504+ // Read remaining bytes from buffer
8505+ n = strm.read (buf, sizeof (buf) / 2 );
8506+ EXPECT_EQ (sizeof (buf) / 2 , n);
8507+
8508+ // Buffer should be empty
8509+ EXPECT_FALSE (strm.is_readable ());
8510+
8511+ // Signal server to close connection
8512+ strm.write (buf, sizeof (buf));
8513+ std::this_thread::sleep_for (delay);
8514+
8515+ // Server should have closed connection
8516+ n = strm.read (buf, sizeof (buf));
8517+ EXPECT_EQ (0 , n);
8518+
8519+ return true ;
8520+ };
8521+
8522+ cli.set_read_timeout (0 , timeout_us);
8523+
8524+ Response res;
8525+ Error error;
8526+ ASSERT_TRUE (cli.send (req, res, error));
8527+ EXPECT_EQ (StatusCode::OK_200, res.status );
8528+ EXPECT_EQ (res.headers .size (), 1 );
8529+ EXPECT_TRUE (res.body .empty ());
8530+ }
8531+
8532+ TEST (StreamHandlerTest, Basic) {
8533+ Server svr;
8534+ Client cli (HOST, PORT);
8535+
8536+ stream_handler_test (svr, cli);
8537+ }
8538+
8539+ #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
8540+ TEST (StreamHandlerTest, BasicSSL) {
8541+ SSLServer svr (SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE);
8542+ SSLClient cli (HOST, PORT);
8543+ cli.enable_server_certificate_verification (false );
8544+
8545+ stream_handler_test (svr, cli);
8546+ }
8547+ #endif
0 commit comments