@@ -8434,3 +8434,114 @@ TEST(ClientInThreadTest, Issue2068) {
8434
8434
t.join ();
8435
8435
}
8436
8436
}
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