fix: Fix bugs in new webserver (#1780)

Fixes #919.

Fixes bugs for new webserver:
- Unhandled exception when closing already closed websocket
- No pings for plain websocket connection
- Server drops websocket connection when client responds to pings but
doesn't send anything

Also changing API of ng connections. Now timeout is set by a separate
method instead of providing it for each call.
This commit is contained in:
Sergey Kuznetsov
2024-12-19 15:14:04 +00:00
committed by GitHub
parent c4b87d2a0a
commit 7d4e3619b0
13 changed files with 238 additions and 204 deletions

View File

@@ -66,9 +66,11 @@ struct HttpConnectionTests : SyncAsioContextTest {
auto expectedSocket = httpServer_.accept(yield);
[&]() { ASSERT_TRUE(expectedSocket.has_value()) << expectedSocket.error().message(); }();
auto ip = expectedSocket->remote_endpoint().address().to_string();
return PlainHttpConnection{
PlainHttpConnection connection{
std::move(expectedSocket).value(), std::move(ip), boost::beast::flat_buffer{}, tagDecoratorFactory_
};
connection.setTimeout(std::chrono::milliseconds{100});
return connection;
}
};
@@ -100,7 +102,7 @@ TEST_F(HttpConnectionTests, Receive)
runSpawn([this](boost::asio::yield_context yield) {
auto connection = acceptConnection(yield);
auto expectedRequest = connection.receive(yield, std::chrono::milliseconds{100});
auto expectedRequest = connection.receive(yield);
ASSERT_TRUE(expectedRequest.has_value()) << expectedRequest.error().message();
ASSERT_TRUE(expectedRequest->isHttp());
@@ -124,7 +126,8 @@ TEST_F(HttpConnectionTests, ReceiveTimeout)
runSpawn([this](boost::asio::yield_context yield) {
auto connection = acceptConnection(yield);
auto expectedRequest = connection.receive(yield, std::chrono::milliseconds{1});
connection.setTimeout(std::chrono::milliseconds{1});
auto expectedRequest = connection.receive(yield);
EXPECT_FALSE(expectedRequest.has_value());
});
}
@@ -139,7 +142,8 @@ TEST_F(HttpConnectionTests, ReceiveClientDisconnected)
runSpawn([this](boost::asio::yield_context yield) {
auto connection = acceptConnection(yield);
auto expectedRequest = connection.receive(yield, std::chrono::milliseconds{1});
connection.setTimeout(std::chrono::milliseconds{1});
auto expectedRequest = connection.receive(yield);
EXPECT_FALSE(expectedRequest.has_value());
});
}
@@ -166,7 +170,7 @@ TEST_F(HttpConnectionTests, Send)
runSpawn([this, &response](boost::asio::yield_context yield) {
auto connection = acceptConnection(yield);
auto maybeError = connection.send(response, yield, std::chrono::milliseconds{100});
auto maybeError = connection.send(response, yield);
[&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError->message(); }();
});
}
@@ -197,7 +201,7 @@ TEST_F(HttpConnectionTests, SendMultipleTimes)
auto connection = acceptConnection(yield);
for ([[maybe_unused]] auto _i : std::ranges::iota_view{0, 3}) {
auto maybeError = connection.send(response, yield, std::chrono::milliseconds{100});
auto maybeError = connection.send(response, yield);
[&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError->message(); }();
}
});
@@ -213,11 +217,12 @@ TEST_F(HttpConnectionTests, SendClientDisconnected)
});
runSpawn([this, &response](boost::asio::yield_context yield) {
auto connection = acceptConnection(yield);
auto maybeError = connection.send(response, yield, std::chrono::milliseconds{1});
connection.setTimeout(std::chrono::milliseconds{1});
auto maybeError = connection.send(response, yield);
size_t counter{1};
while (not maybeError.has_value() and counter < 100) {
++counter;
maybeError = connection.send(response, yield, std::chrono::milliseconds{1});
maybeError = connection.send(response, yield);
}
EXPECT_TRUE(maybeError.has_value());
EXPECT_LT(counter, 100);
@@ -241,7 +246,8 @@ TEST_F(HttpConnectionTests, Close)
runSpawn([this](boost::asio::yield_context yield) {
auto connection = acceptConnection(yield);
connection.close(yield, std::chrono::milliseconds{1});
connection.setTimeout(std::chrono::milliseconds{1});
connection.close(yield);
});
}
@@ -257,7 +263,7 @@ TEST_F(HttpConnectionTests, IsUpgradeRequested_GotHttpRequest)
runSpawn([this](boost::asio::yield_context yield) {
auto connection = acceptConnection(yield);
auto result = connection.isUpgradeRequested(yield, std::chrono::milliseconds{100});
auto result = connection.isUpgradeRequested(yield);
[&]() { ASSERT_TRUE(result.has_value()) << result.error().message(); }();
EXPECT_FALSE(result.value());
});
@@ -272,7 +278,8 @@ TEST_F(HttpConnectionTests, IsUpgradeRequested_FailedToFetch)
runSpawn([this](boost::asio::yield_context yield) {
auto connection = acceptConnection(yield);
auto result = connection.isUpgradeRequested(yield, std::chrono::milliseconds{1});
connection.setTimeout(std::chrono::milliseconds{1});
auto result = connection.isUpgradeRequested(yield);
EXPECT_FALSE(result.has_value());
});
}
@@ -288,7 +295,7 @@ TEST_F(HttpConnectionTests, Upgrade)
runSpawn([this](boost::asio::yield_context yield) {
auto connection = acceptConnection(yield);
auto const expectedResult = connection.isUpgradeRequested(yield, std::chrono::milliseconds{100});
auto const expectedResult = connection.isUpgradeRequested(yield);
[&]() { ASSERT_TRUE(expectedResult.has_value()) << expectedResult.error().message(); }();
[&]() { ASSERT_TRUE(expectedResult.value()); }();