mirror of
https://github.com/XRPLF/clio.git
synced 2025-11-04 20:05:51 +00:00
feat: Cache state endpoint (#2642)
This commit is contained in:
@@ -189,6 +189,7 @@ ClioApplication::run(bool const useNgWebServer)
|
||||
|
||||
httpServer->onGet("/metrics", MetricsHandler{adminVerifier});
|
||||
httpServer->onGet("/health", HealthCheckHandler{});
|
||||
httpServer->onGet("/cache_state", CacheStateHandler{cache});
|
||||
auto requestHandler = RequestHandler{adminVerifier, handler};
|
||||
httpServer->onPost("/", requestHandler);
|
||||
httpServer->onWs(std::move(requestHandler));
|
||||
@@ -214,7 +215,7 @@ ClioApplication::run(bool const useNgWebServer)
|
||||
// Init the web server
|
||||
auto handler = std::make_shared<web::RPCServerHandler<RPCEngineType>>(config_, backend, rpcEngine, etl, dosGuard);
|
||||
|
||||
auto const httpServer = web::makeHttpServer(config_, ioc, dosGuard, handler);
|
||||
auto const httpServer = web::makeHttpServer(config_, ioc, dosGuard, handler, cache);
|
||||
|
||||
// Blocks until stopped.
|
||||
// When stopped, shared_ptrs fall out of scope
|
||||
|
||||
@@ -120,4 +120,34 @@ HealthCheckHandler::operator()(
|
||||
return web::ng::Response{boost::beast::http::status::ok, kHEALTH_CHECK_HTML, request};
|
||||
}
|
||||
|
||||
web::ng::Response
|
||||
CacheStateHandler::operator()(
|
||||
web::ng::Request const& request,
|
||||
web::ng::ConnectionMetadata&,
|
||||
web::SubscriptionContextPtr,
|
||||
boost::asio::yield_context
|
||||
)
|
||||
{
|
||||
static constexpr auto kCACHE_CHECK_LOADED_HTML = R"html(
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head><title>Cache state</title></head>
|
||||
<body><h1>Cache state</h1><p>Cache is fully loaded</p></body>
|
||||
</html>
|
||||
)html";
|
||||
|
||||
static constexpr auto kCACHE_CHECK_NOT_LOADED_HTML = R"html(
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head><title>Cache state</title></head>
|
||||
<body><h1>Cache state</h1><p>Cache is not yet loaded</p></body>
|
||||
</html>
|
||||
)html";
|
||||
|
||||
if (cache_.get().isFull())
|
||||
return web::ng::Response{boost::beast::http::status::ok, kCACHE_CHECK_LOADED_HTML, request};
|
||||
|
||||
return web::ng::Response{boost::beast::http::status::service_unavailable, kCACHE_CHECK_NOT_LOADED_HTML, request};
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "data/LedgerCacheInterface.hpp"
|
||||
#include "rpc/Errors.hpp"
|
||||
#include "util/log/Logger.hpp"
|
||||
#include "web/AdminVerificationStrategy.hpp"
|
||||
@@ -163,6 +164,37 @@ public:
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A function object that handles the cache state check endpoint.
|
||||
*/
|
||||
class CacheStateHandler {
|
||||
std::reference_wrapper<data::LedgerCacheInterface const> cache_;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new CacheStateHandler object.
|
||||
*
|
||||
* @param cache The ledger cache to use.
|
||||
*/
|
||||
CacheStateHandler(data::LedgerCacheInterface const& cache) : cache_{cache}
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The call of the function object.
|
||||
*
|
||||
* @param request The request to handle.
|
||||
* @return The response to the request
|
||||
*/
|
||||
web::ng::Response
|
||||
operator()(
|
||||
web::ng::Request const& request,
|
||||
web::ng::ConnectionMetadata&,
|
||||
web::SubscriptionContextPtr,
|
||||
boost::asio::yield_context
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A function object that handles the websocket endpoint.
|
||||
*
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "data/LedgerCacheInterface.hpp"
|
||||
#include "util/Taggable.hpp"
|
||||
#include "web/AdminVerificationStrategy.hpp"
|
||||
#include "web/PlainWsSession.hpp"
|
||||
@@ -69,6 +70,7 @@ public:
|
||||
* @param tagFactory A factory that is used to generate tags to track requests and sessions
|
||||
* @param dosGuard The denial of service guard to use
|
||||
* @param handler The server handler to use
|
||||
* @param cache The ledger cache to use
|
||||
* @param buffer Buffer with initial data received from the peer
|
||||
* @param maxWsSendingQueueSize The maximum size of the sending queue for websocket
|
||||
*/
|
||||
@@ -80,6 +82,7 @@ public:
|
||||
std::reference_wrapper<util::TagDecoratorFactory const> tagFactory,
|
||||
std::reference_wrapper<dosguard::DOSGuardInterface> dosGuard,
|
||||
std::shared_ptr<HandlerType> const& handler,
|
||||
std::reference_wrapper<data::LedgerCacheInterface const> cache,
|
||||
boost::beast::flat_buffer buffer,
|
||||
std::uint32_t maxWsSendingQueueSize
|
||||
)
|
||||
@@ -90,6 +93,7 @@ public:
|
||||
std::move(proxyIpResolver),
|
||||
dosGuard,
|
||||
handler,
|
||||
cache,
|
||||
std::move(buffer)
|
||||
)
|
||||
, stream_(std::move(socket))
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "data/LedgerCacheInterface.hpp"
|
||||
#include "util/Taggable.hpp"
|
||||
#include "util/log/Logger.hpp"
|
||||
#include "web/AdminVerificationStrategy.hpp"
|
||||
@@ -85,6 +86,7 @@ class Detector : public std::enable_shared_from_this<Detector<PlainSessionType,
|
||||
std::reference_wrapper<util::TagDecoratorFactory const> tagFactory_;
|
||||
std::reference_wrapper<dosguard::DOSGuardInterface> const dosGuard_;
|
||||
std::shared_ptr<HandlerType> const handler_;
|
||||
std::reference_wrapper<data::LedgerCacheInterface const> cache_;
|
||||
boost::beast::flat_buffer buffer_;
|
||||
std::shared_ptr<AdminVerificationStrategy> const adminVerification_;
|
||||
std::uint32_t maxWsSendingQueueSize_;
|
||||
@@ -99,6 +101,7 @@ public:
|
||||
* @param tagFactory A factory that is used to generate tags to track requests and sessions
|
||||
* @param dosGuard The denial of service guard to use
|
||||
* @param handler The server handler to use
|
||||
* @param cache The ledger cache to use
|
||||
* @param adminVerification The admin verification strategy to use
|
||||
* @param maxWsSendingQueueSize The maximum size of the sending queue for websocket
|
||||
* @param proxyIpResolver The client ip resolver if a request was forwarded by a proxy
|
||||
@@ -109,6 +112,7 @@ public:
|
||||
std::reference_wrapper<util::TagDecoratorFactory const> tagFactory,
|
||||
std::reference_wrapper<dosguard::DOSGuardInterface> dosGuard,
|
||||
std::shared_ptr<HandlerType> handler,
|
||||
std::reference_wrapper<data::LedgerCacheInterface const> cache,
|
||||
std::shared_ptr<AdminVerificationStrategy> adminVerification,
|
||||
std::uint32_t maxWsSendingQueueSize,
|
||||
std::shared_ptr<ProxyIpResolver> proxyIpResolver
|
||||
@@ -118,6 +122,7 @@ public:
|
||||
, tagFactory_(std::cref(tagFactory))
|
||||
, dosGuard_(dosGuard)
|
||||
, handler_(std::move(handler))
|
||||
, cache_(cache)
|
||||
, adminVerification_(std::move(adminVerification))
|
||||
, maxWsSendingQueueSize_(maxWsSendingQueueSize)
|
||||
, proxyIpResolver_(std::move(proxyIpResolver))
|
||||
@@ -179,6 +184,7 @@ public:
|
||||
tagFactory_,
|
||||
dosGuard_,
|
||||
handler_,
|
||||
cache_,
|
||||
std::move(buffer_),
|
||||
maxWsSendingQueueSize_
|
||||
)
|
||||
@@ -194,6 +200,7 @@ public:
|
||||
tagFactory_,
|
||||
dosGuard_,
|
||||
handler_,
|
||||
cache_,
|
||||
std::move(buffer_),
|
||||
maxWsSendingQueueSize_
|
||||
)
|
||||
@@ -223,6 +230,7 @@ class Server : public std::enable_shared_from_this<Server<PlainSessionType, SslS
|
||||
util::TagDecoratorFactory tagFactory_;
|
||||
std::reference_wrapper<dosguard::DOSGuardInterface> dosGuard_;
|
||||
std::shared_ptr<HandlerType> handler_;
|
||||
std::reference_wrapper<data::LedgerCacheInterface const> cache_;
|
||||
tcp::acceptor acceptor_;
|
||||
std::shared_ptr<AdminVerificationStrategy> adminVerification_;
|
||||
std::uint32_t maxWsSendingQueueSize_;
|
||||
@@ -238,6 +246,7 @@ public:
|
||||
* @param tagFactory A factory that is used to generate tags to track requests and sessions
|
||||
* @param dosGuard The denial of service guard to use
|
||||
* @param handler The server handler to use
|
||||
* @param cache The ledger cache to use
|
||||
* @param adminVerification The admin verification strategy to use
|
||||
* @param maxWsSendingQueueSize The maximum size of the sending queue for websocket
|
||||
* @param proxyIpResolver The client ip resolver if a request was forwarded by a proxy
|
||||
@@ -249,6 +258,7 @@ public:
|
||||
util::TagDecoratorFactory tagFactory,
|
||||
dosguard::DOSGuardInterface& dosGuard,
|
||||
std::shared_ptr<HandlerType> handler,
|
||||
std::reference_wrapper<data::LedgerCacheInterface const> cache,
|
||||
std::shared_ptr<AdminVerificationStrategy> adminVerification,
|
||||
std::uint32_t maxWsSendingQueueSize,
|
||||
ProxyIpResolver proxyIpResolver
|
||||
@@ -258,6 +268,7 @@ public:
|
||||
, tagFactory_(tagFactory)
|
||||
, dosGuard_(std::ref(dosGuard))
|
||||
, handler_(std::move(handler))
|
||||
, cache_(cache)
|
||||
, acceptor_(boost::asio::make_strand(ioc))
|
||||
, adminVerification_(std::move(adminVerification))
|
||||
, maxWsSendingQueueSize_(maxWsSendingQueueSize)
|
||||
@@ -320,6 +331,7 @@ private:
|
||||
std::cref(tagFactory_),
|
||||
dosGuard_,
|
||||
handler_,
|
||||
cache_,
|
||||
adminVerification_,
|
||||
maxWsSendingQueueSize_,
|
||||
proxyIpResolver_
|
||||
@@ -343,6 +355,7 @@ using HttpServer = Server<HttpSession, SslHttpSession, HandlerType>;
|
||||
* @param ioc The server will run under this io_context
|
||||
* @param dosGuard The dos guard to protect the server
|
||||
* @param handler The handler to process the request
|
||||
* @param cache The ledger cache to use
|
||||
* @return The server instance
|
||||
*/
|
||||
template <typename HandlerType>
|
||||
@@ -351,7 +364,8 @@ makeHttpServer(
|
||||
util::config::ClioConfigDefinition const& config,
|
||||
boost::asio::io_context& ioc,
|
||||
dosguard::DOSGuardInterface& dosGuard,
|
||||
std::shared_ptr<HandlerType> const& handler
|
||||
std::shared_ptr<HandlerType> const& handler,
|
||||
std::reference_wrapper<data::LedgerCacheInterface const> cache
|
||||
)
|
||||
{
|
||||
static util::Logger const log{"WebServer"}; // NOLINT(readability-identifier-naming)
|
||||
@@ -385,6 +399,7 @@ makeHttpServer(
|
||||
util::TagDecoratorFactory(config),
|
||||
dosGuard,
|
||||
handler,
|
||||
cache,
|
||||
std::move(expectedAdminVerification).value(),
|
||||
maxWsSendingQueueSize,
|
||||
std::move(proxyIpResolver)
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "data/LedgerCacheInterface.hpp"
|
||||
#include "util/Taggable.hpp"
|
||||
#include "web/AdminVerificationStrategy.hpp"
|
||||
#include "web/ProxyIpResolver.hpp"
|
||||
@@ -76,6 +77,7 @@ public:
|
||||
* @param tagFactory A factory that is used to generate tags to track requests and sessions
|
||||
* @param dosGuard The denial of service guard to use
|
||||
* @param handler The server handler to use
|
||||
* @param cache The ledger cache to use
|
||||
* @param buffer Buffer with initial data received from the peer
|
||||
* @param maxWsSendingQueueSize The maximum size of the sending queue for websocket
|
||||
*/
|
||||
@@ -88,6 +90,7 @@ public:
|
||||
std::reference_wrapper<util::TagDecoratorFactory const> tagFactory,
|
||||
std::reference_wrapper<dosguard::DOSGuardInterface> dosGuard,
|
||||
std::shared_ptr<HandlerType> const& handler,
|
||||
std::reference_wrapper<data::LedgerCacheInterface const> cache,
|
||||
boost::beast::flat_buffer buffer,
|
||||
std::uint32_t maxWsSendingQueueSize
|
||||
)
|
||||
@@ -98,6 +101,7 @@ public:
|
||||
std::move(proxyIpResolver),
|
||||
dosGuard,
|
||||
handler,
|
||||
cache,
|
||||
std::move(buffer)
|
||||
)
|
||||
, stream_(std::move(socket), ctx)
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "data/LedgerCacheInterface.hpp"
|
||||
#include "rpc/Errors.hpp"
|
||||
#include "util/Assert.hpp"
|
||||
#include "util/Taggable.hpp"
|
||||
@@ -71,6 +72,22 @@ static constexpr auto kHEALTH_CHECK_HTML = R"html(
|
||||
</html>
|
||||
)html";
|
||||
|
||||
static constexpr auto kCACHE_CHECK_LOADED_HTML = R"html(
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head><title>Cache state</title></head>
|
||||
<body><h1>Cache state</h1><p>Cache is fully loaded</p></body>
|
||||
</html>
|
||||
)html";
|
||||
|
||||
static constexpr auto kCACHE_CHECK_NOT_LOADED_HTML = R"html(
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head><title>Cache state</title></head>
|
||||
<body><h1>Cache state</h1><p>Cache is not yet loaded</p></body>
|
||||
</html>
|
||||
)html";
|
||||
|
||||
using tcp = boost::asio::ip::tcp;
|
||||
|
||||
/**
|
||||
@@ -128,6 +145,7 @@ protected:
|
||||
http::request<http::string_body> req_;
|
||||
std::reference_wrapper<dosguard::DOSGuardInterface> dosGuard_;
|
||||
std::shared_ptr<HandlerType> const handler_;
|
||||
std::reference_wrapper<data::LedgerCacheInterface const> cache_;
|
||||
util::Logger log_{"WebServer"};
|
||||
util::Logger perfLog_{"Performance"};
|
||||
|
||||
@@ -169,6 +187,7 @@ public:
|
||||
std::shared_ptr<ProxyIpResolver> proxyIpResolver,
|
||||
std::reference_wrapper<dosguard::DOSGuardInterface> dosGuard,
|
||||
std::shared_ptr<HandlerType> handler,
|
||||
std::reference_wrapper<data::LedgerCacheInterface const> cache,
|
||||
boost::beast::flat_buffer buffer
|
||||
)
|
||||
: ConnectionBase(tagFactory, ip)
|
||||
@@ -178,6 +197,7 @@ public:
|
||||
, buffer_(std::move(buffer))
|
||||
, dosGuard_(dosGuard)
|
||||
, handler_(std::move(handler))
|
||||
, cache_(cache)
|
||||
{
|
||||
LOG(perfLog_.debug()) << tag() << "http session created";
|
||||
dosGuard_.get().increment(ip);
|
||||
@@ -222,6 +242,13 @@ public:
|
||||
if (req_.method() == http::verb::get and req_.target() == "/health")
|
||||
return sender_(httpResponse(http::status::ok, "text/html", kHEALTH_CHECK_HTML));
|
||||
|
||||
if (req_.method() == http::verb::get and req_.target() == "/cache_state") {
|
||||
if (cache_.get().isFull())
|
||||
return sender_(httpResponse(http::status::ok, "text/html", kCACHE_CHECK_LOADED_HTML));
|
||||
|
||||
return sender_(httpResponse(http::status::service_unavailable, "text/html", kCACHE_CHECK_NOT_LOADED_HTML));
|
||||
}
|
||||
|
||||
if (auto resolvedIp = proxyIpResolver_->resolveClientIp(clientIp_, req_); resolvedIp != clientIp_) {
|
||||
LOG(log_.info()) << tag() << "Detected a forwarded request from proxy. Proxy ip: " << clientIp_
|
||||
<< ". Resolved client ip: " << resolvedIp;
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "app/WebHandlers.hpp"
|
||||
#include "rpc/Errors.hpp"
|
||||
#include "util/AsioContextTestFixture.hpp"
|
||||
#include "util/MockLedgerCache.hpp"
|
||||
#include "util/MockPrometheus.hpp"
|
||||
#include "util/Taggable.hpp"
|
||||
#include "util/config/ConfigDefinition.hpp"
|
||||
@@ -149,6 +150,32 @@ TEST_F(HealthCheckHandlerTests, Call)
|
||||
});
|
||||
}
|
||||
|
||||
struct CacheStateHandlerTests : SyncAsioContextTest, WebHandlersTest {
|
||||
web::ng::Request request{http::request<http::string_body>{http::verb::get, "/", 11}};
|
||||
MockLedgerCache cache;
|
||||
CacheStateHandler cacheStateHandler{cache};
|
||||
};
|
||||
|
||||
TEST_F(CacheStateHandlerTests, CallWithCacheLoaded)
|
||||
{
|
||||
EXPECT_CALL(cache, isFull()).WillRepeatedly(testing::Return(true));
|
||||
runSpawn([&](boost::asio::yield_context yield) {
|
||||
auto response = cacheStateHandler(request, connectionMock, nullptr, yield);
|
||||
auto const httpResponse = std::move(response).intoHttpResponse();
|
||||
EXPECT_EQ(httpResponse.result(), boost::beast::http::status::ok);
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(CacheStateHandlerTests, CallWithoutCacheLoaded)
|
||||
{
|
||||
EXPECT_CALL(cache, isFull()).WillRepeatedly(testing::Return(false));
|
||||
runSpawn([&](boost::asio::yield_context yield) {
|
||||
auto response = cacheStateHandler(request, connectionMock, nullptr, yield);
|
||||
auto const httpResponse = std::move(response).intoHttpResponse();
|
||||
EXPECT_EQ(httpResponse.result(), boost::beast::http::status::service_unavailable);
|
||||
});
|
||||
}
|
||||
|
||||
struct RequestHandlerTest : SyncAsioContextTest, WebHandlersTest {
|
||||
AdminVerificationStrategyStrictMockPtr adminVerifier{
|
||||
std::make_shared<testing::StrictMock<AdminVerificationStrategyMock>>()
|
||||
|
||||
@@ -17,7 +17,9 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include "data/LedgerCacheInterface.hpp"
|
||||
#include "util/AssignRandomPort.hpp"
|
||||
#include "util/MockLedgerCache.hpp"
|
||||
#include "util/MockPrometheus.hpp"
|
||||
#include "util/TestHttpClient.hpp"
|
||||
#include "util/TestWebSocketClient.hpp"
|
||||
@@ -48,11 +50,13 @@
|
||||
#include <boost/json/value.hpp>
|
||||
#include <boost/system/system_error.hpp>
|
||||
#include <fmt/format.h>
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <test_data/SslCert.hpp>
|
||||
|
||||
#include <condition_variable>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
@@ -223,15 +227,18 @@ makeServerSync(
|
||||
util::config::ClioConfigDefinition const& config,
|
||||
boost::asio::io_context& ioc,
|
||||
web::dosguard::DOSGuardInterface& dosGuard,
|
||||
std::shared_ptr<Executor> const& handler
|
||||
std::shared_ptr<Executor> const& handler,
|
||||
std::reference_wrapper<data::LedgerCacheInterface const> cache
|
||||
)
|
||||
{
|
||||
auto server = std::shared_ptr<web::HttpServer<Executor>>();
|
||||
|
||||
std::mutex m;
|
||||
std::condition_variable cv;
|
||||
bool ready = false;
|
||||
|
||||
boost::asio::dispatch(ioc.get_executor(), [&]() mutable {
|
||||
server = web::makeHttpServer(config, ioc, dosGuard, handler);
|
||||
server = web::makeHttpServer(config, ioc, dosGuard, handler, cache);
|
||||
{
|
||||
std::lock_guard const lk(m);
|
||||
ready = true;
|
||||
@@ -249,8 +256,9 @@ makeServerSync(
|
||||
|
||||
TEST_F(WebServerTest, Http)
|
||||
{
|
||||
auto cache = MockLedgerCache();
|
||||
auto const e = std::make_shared<EchoExecutor>();
|
||||
auto const server = makeServerSync(cfg, ctx, dosGuard, e);
|
||||
auto const server = makeServerSync(cfg, ctx, dosGuard, e, cache);
|
||||
auto const [status, res] = HttpSyncClient::post("localhost", port, R"JSON({"Hello":1})JSON");
|
||||
EXPECT_EQ(res, R"JSON({"Hello":1})JSON");
|
||||
EXPECT_EQ(status, boost::beast::http::status::ok);
|
||||
@@ -258,8 +266,9 @@ TEST_F(WebServerTest, Http)
|
||||
|
||||
TEST_F(WebServerTest, Ws)
|
||||
{
|
||||
auto cache = MockLedgerCache();
|
||||
auto e = std::make_shared<EchoExecutor>();
|
||||
auto const server = makeServerSync(cfg, ctx, dosGuard, e);
|
||||
auto const server = makeServerSync(cfg, ctx, dosGuard, e, cache);
|
||||
WebSocketSyncClient wsClient;
|
||||
wsClient.connect("localhost", port);
|
||||
auto const res = wsClient.syncPost(R"JSON({"Hello":1})JSON");
|
||||
@@ -269,8 +278,9 @@ TEST_F(WebServerTest, Ws)
|
||||
|
||||
TEST_F(WebServerTest, HttpInternalError)
|
||||
{
|
||||
auto cache = MockLedgerCache();
|
||||
auto const e = std::make_shared<ExceptionExecutor>();
|
||||
auto const server = makeServerSync(cfg, ctx, dosGuard, e);
|
||||
auto const server = makeServerSync(cfg, ctx, dosGuard, e, cache);
|
||||
auto const [status, res] = HttpSyncClient::post("localhost", port, R"JSON({})JSON");
|
||||
EXPECT_EQ(
|
||||
res,
|
||||
@@ -281,8 +291,9 @@ TEST_F(WebServerTest, HttpInternalError)
|
||||
|
||||
TEST_F(WebServerTest, WsInternalError)
|
||||
{
|
||||
auto cache = MockLedgerCache();
|
||||
auto e = std::make_shared<ExceptionExecutor>();
|
||||
auto const server = makeServerSync(cfg, ctx, dosGuard, e);
|
||||
auto const server = makeServerSync(cfg, ctx, dosGuard, e, cache);
|
||||
WebSocketSyncClient wsClient;
|
||||
wsClient.connect("localhost", port);
|
||||
auto const res = wsClient.syncPost(R"JSON({"id":"id1"})JSON");
|
||||
@@ -295,8 +306,9 @@ TEST_F(WebServerTest, WsInternalError)
|
||||
|
||||
TEST_F(WebServerTest, WsInternalErrorNotJson)
|
||||
{
|
||||
auto cache = MockLedgerCache();
|
||||
auto e = std::make_shared<ExceptionExecutor>();
|
||||
auto const server = makeServerSync(cfg, ctx, dosGuard, e);
|
||||
auto const server = makeServerSync(cfg, ctx, dosGuard, e, cache);
|
||||
WebSocketSyncClient wsClient;
|
||||
wsClient.connect("localhost", port);
|
||||
auto const res = wsClient.syncPost("not json");
|
||||
@@ -314,7 +326,8 @@ TEST_F(WebServerTest, IncompleteSslConfig)
|
||||
auto jsonConfig = generateJSONWithDynamicPort(port);
|
||||
jsonConfig.as_object()["ssl_key_file"] = sslKeyFile.path;
|
||||
|
||||
auto const server = makeServerSync(getParseServerConfig(jsonConfig), ctx, dosGuard, e);
|
||||
auto cache = MockLedgerCache();
|
||||
auto const server = makeServerSync(getParseServerConfig(jsonConfig), ctx, dosGuard, e, cache);
|
||||
EXPECT_EQ(server, nullptr);
|
||||
}
|
||||
|
||||
@@ -326,24 +339,27 @@ TEST_F(WebServerTest, WrongSslConfig)
|
||||
jsonConfig.as_object()["ssl_key_file"] = sslKeyFile.path;
|
||||
jsonConfig.as_object()["ssl_cert_file"] = "wrong_path";
|
||||
|
||||
auto const server = makeServerSync(getParseServerConfig(jsonConfig), ctx, dosGuard, e);
|
||||
auto cache = MockLedgerCache();
|
||||
auto const server = makeServerSync(getParseServerConfig(jsonConfig), ctx, dosGuard, e, cache);
|
||||
EXPECT_EQ(server, nullptr);
|
||||
}
|
||||
|
||||
TEST_F(WebServerTest, Https)
|
||||
{
|
||||
auto cache = MockLedgerCache();
|
||||
auto const e = std::make_shared<EchoExecutor>();
|
||||
cfg = getParseServerConfig(addSslConfig(generateJSONWithDynamicPort(port)));
|
||||
auto const server = makeServerSync(cfg, ctx, dosGuard, e);
|
||||
auto const server = makeServerSync(cfg, ctx, dosGuard, e, cache);
|
||||
auto const res = HttpsSyncClient::syncPost("localhost", port, R"JSON({"Hello":1})JSON");
|
||||
EXPECT_EQ(res, R"JSON({"Hello":1})JSON");
|
||||
}
|
||||
|
||||
TEST_F(WebServerTest, Wss)
|
||||
{
|
||||
auto cache = MockLedgerCache();
|
||||
auto e = std::make_shared<EchoExecutor>();
|
||||
cfg = getParseServerConfig(addSslConfig(generateJSONWithDynamicPort(port)));
|
||||
auto server = makeServerSync(cfg, ctx, dosGuard, e);
|
||||
auto server = makeServerSync(cfg, ctx, dosGuard, e, cache);
|
||||
WebServerSslSyncClient wsClient;
|
||||
wsClient.connect("localhost", port);
|
||||
auto const res = wsClient.syncPost(R"JSON({"Hello":1})JSON");
|
||||
@@ -354,8 +370,9 @@ TEST_F(WebServerTest, Wss)
|
||||
TEST_F(WebServerTest, HttpPayloadOverload)
|
||||
{
|
||||
std::string const s100(100, 'a');
|
||||
auto cache = MockLedgerCache();
|
||||
auto const e = std::make_shared<EchoExecutor>();
|
||||
auto server = makeServerSync(cfg, ctx, dosGuardOverload, e);
|
||||
auto server = makeServerSync(cfg, ctx, dosGuardOverload, e, cache);
|
||||
auto const [status, res] =
|
||||
HttpSyncClient::post("localhost", port, fmt::format(R"JSON({{"payload":"{}"}})JSON", s100));
|
||||
EXPECT_EQ(
|
||||
@@ -368,8 +385,9 @@ TEST_F(WebServerTest, HttpPayloadOverload)
|
||||
TEST_F(WebServerTest, WsPayloadOverload)
|
||||
{
|
||||
std::string const s100(100, 'a');
|
||||
auto cache = MockLedgerCache();
|
||||
auto const e = std::make_shared<EchoExecutor>();
|
||||
auto server = makeServerSync(cfg, ctx, dosGuardOverload, e);
|
||||
auto server = makeServerSync(cfg, ctx, dosGuardOverload, e, cache);
|
||||
WebSocketSyncClient wsClient;
|
||||
wsClient.connect("localhost", port);
|
||||
auto const res = wsClient.syncPost(fmt::format(R"JSON({{"payload":"{}"}})JSON", s100));
|
||||
@@ -382,8 +400,9 @@ TEST_F(WebServerTest, WsPayloadOverload)
|
||||
|
||||
TEST_F(WebServerTest, WsTooManyConnection)
|
||||
{
|
||||
auto cache = MockLedgerCache();
|
||||
auto const e = std::make_shared<EchoExecutor>();
|
||||
auto server = makeServerSync(cfg, ctx, dosGuardOverload, e);
|
||||
auto server = makeServerSync(cfg, ctx, dosGuardOverload, e, cache);
|
||||
// max connection is 2, exception should happen when the third connection is made
|
||||
WebSocketSyncClient wsClient1;
|
||||
wsClient1.connect("localhost", port);
|
||||
@@ -404,18 +423,46 @@ TEST_F(WebServerTest, WsTooManyConnection)
|
||||
|
||||
TEST_F(WebServerTest, HealthCheck)
|
||||
{
|
||||
auto cache = MockLedgerCache();
|
||||
auto e = std::make_shared<ExceptionExecutor>(); // request handled before we get to executor
|
||||
auto const server = makeServerSync(cfg, ctx, dosGuard, e);
|
||||
auto const server = makeServerSync(cfg, ctx, dosGuard, e, cache);
|
||||
auto const [status, res] = HttpSyncClient::get("localhost", port, "", "/health");
|
||||
|
||||
EXPECT_FALSE(res.empty());
|
||||
EXPECT_EQ(status, boost::beast::http::status::ok);
|
||||
}
|
||||
|
||||
TEST_F(WebServerTest, CacheStateCheckWithLoadedCache)
|
||||
{
|
||||
auto cache = MockLedgerCache();
|
||||
EXPECT_CALL(cache, isFull()).WillRepeatedly(testing::Return(true));
|
||||
|
||||
auto e = std::make_shared<ExceptionExecutor>(); // request handled before we get to executor
|
||||
auto const server = makeServerSync(cfg, ctx, dosGuard, e, cache);
|
||||
auto const [status, res] = HttpSyncClient::get("localhost", port, "", "/cache_state");
|
||||
|
||||
EXPECT_FALSE(res.empty());
|
||||
EXPECT_EQ(status, boost::beast::http::status::ok);
|
||||
}
|
||||
|
||||
TEST_F(WebServerTest, CacheStateCheckWithoutLoadedCache)
|
||||
{
|
||||
auto cache = MockLedgerCache();
|
||||
EXPECT_CALL(cache, isFull()).WillRepeatedly(testing::Return(false));
|
||||
|
||||
auto e = std::make_shared<ExceptionExecutor>(); // request handled before we get to executor
|
||||
auto const server = makeServerSync(cfg, ctx, dosGuard, e, cache);
|
||||
auto const [status, res] = HttpSyncClient::get("localhost", port, "", "/cache_state");
|
||||
|
||||
EXPECT_FALSE(res.empty());
|
||||
EXPECT_EQ(status, boost::beast::http::status::service_unavailable);
|
||||
}
|
||||
|
||||
TEST_F(WebServerTest, GetOtherThanHealthCheck)
|
||||
{
|
||||
auto cache = MockLedgerCache();
|
||||
auto e = std::make_shared<ExceptionExecutor>(); // request handled before we get to executor
|
||||
auto const server = makeServerSync(cfg, ctx, dosGuard, e);
|
||||
auto const server = makeServerSync(cfg, ctx, dosGuard, e, cache);
|
||||
auto const [status, res] = HttpSyncClient::get("localhost", port, "", "/");
|
||||
|
||||
EXPECT_FALSE(res.empty());
|
||||
@@ -539,9 +586,10 @@ class WebServerAdminTest : public WebServerTest, public ::testing::WithParamInte
|
||||
|
||||
TEST_P(WebServerAdminTest, WsAdminCheck)
|
||||
{
|
||||
auto cache = MockLedgerCache();
|
||||
auto e = std::make_shared<AdminCheckExecutor>();
|
||||
ClioConfigDefinition const serverConfig{getParseAdminServerConfig(boost::json::parse(GetParam().config))};
|
||||
auto server = makeServerSync(serverConfig, ctx, dosGuardOverload, e);
|
||||
auto server = makeServerSync(serverConfig, ctx, dosGuardOverload, e, cache);
|
||||
WebSocketSyncClient wsClient;
|
||||
uint32_t const webServerPort = serverConfig.get<uint32_t>("server.port");
|
||||
wsClient.connect("localhost", std::to_string(webServerPort), GetParam().headers);
|
||||
@@ -553,9 +601,10 @@ TEST_P(WebServerAdminTest, WsAdminCheck)
|
||||
|
||||
TEST_P(WebServerAdminTest, HttpAdminCheck)
|
||||
{
|
||||
auto cache = MockLedgerCache();
|
||||
auto const e = std::make_shared<AdminCheckExecutor>();
|
||||
ClioConfigDefinition const serverConfig{getParseAdminServerConfig(boost::json::parse(GetParam().config))};
|
||||
auto server = makeServerSync(serverConfig, ctx, dosGuardOverload, e);
|
||||
auto server = makeServerSync(serverConfig, ctx, dosGuardOverload, e, cache);
|
||||
std::string const request = "Why hello";
|
||||
uint32_t const webServerPort = serverConfig.get<uint32_t>("server.port");
|
||||
auto const [status, res] =
|
||||
@@ -651,7 +700,9 @@ TEST_F(WebServerTest, AdminErrorCfgTestBothAdminPasswordAndLocalAdminSet)
|
||||
ClioConfigDefinition const serverConfig{
|
||||
getParseAdminServerConfig(boost::json::parse(jsonServerConfigWithBothAdminPasswordAndLocalAdmin))
|
||||
};
|
||||
EXPECT_THROW(web::makeHttpServer(serverConfig, ctx, dosGuardOverload, e), std::logic_error);
|
||||
|
||||
MockLedgerCache cache;
|
||||
EXPECT_THROW(web::makeHttpServer(serverConfig, ctx, dosGuardOverload, e, cache), std::logic_error);
|
||||
}
|
||||
|
||||
TEST_F(WebServerTest, AdminErrorCfgTestBothAdminPasswordAndLocalAdminFalse)
|
||||
@@ -672,19 +723,22 @@ TEST_F(WebServerTest, AdminErrorCfgTestBothAdminPasswordAndLocalAdminFalse)
|
||||
ClioConfigDefinition const serverConfig{
|
||||
getParseAdminServerConfig(boost::json::parse(jsonServerConfigWithNoAdminPasswordAndLocalAdminFalse))
|
||||
};
|
||||
EXPECT_THROW(web::makeHttpServer(serverConfig, ctx, dosGuardOverload, e), std::logic_error);
|
||||
|
||||
MockLedgerCache cache;
|
||||
EXPECT_THROW(web::makeHttpServer(serverConfig, ctx, dosGuardOverload, e, cache), std::logic_error);
|
||||
}
|
||||
|
||||
struct WebServerPrometheusTest : util::prometheus::WithPrometheus, WebServerTest {};
|
||||
|
||||
TEST_F(WebServerPrometheusTest, rejectedWithoutAdminPassword)
|
||||
{
|
||||
auto cache = MockLedgerCache();
|
||||
auto const e = std::make_shared<EchoExecutor>();
|
||||
uint32_t const webServerPort = tests::util::generateFreePort();
|
||||
ClioConfigDefinition const serverConfig{
|
||||
getParseAdminServerConfig(boost::json::parse(jsonServerConfigWithAdminPassword(webServerPort)))
|
||||
};
|
||||
auto server = makeServerSync(serverConfig, ctx, dosGuard, e);
|
||||
auto server = makeServerSync(serverConfig, ctx, dosGuard, e, cache);
|
||||
auto const [status, res] = HttpSyncClient::get("localhost", std::to_string(webServerPort), "", "/metrics");
|
||||
|
||||
EXPECT_EQ(res, "Only admin is allowed to collect metrics");
|
||||
@@ -708,11 +762,12 @@ TEST_F(WebServerPrometheusDisabledTest, rejectedIfPrometheusIsDisabled)
|
||||
webServerPort
|
||||
);
|
||||
|
||||
auto cache = MockLedgerCache();
|
||||
auto const e = std::make_shared<EchoExecutor>();
|
||||
ClioConfigDefinition const serverConfig{
|
||||
getParseAdminServerConfig(boost::json::parse(jsonServerConfigWithDisabledPrometheus))
|
||||
};
|
||||
auto server = makeServerSync(serverConfig, ctx, dosGuard, e);
|
||||
auto server = makeServerSync(serverConfig, ctx, dosGuard, e, cache);
|
||||
auto const [status, res] = HttpSyncClient::get(
|
||||
"localhost",
|
||||
std::to_string(webServerPort),
|
||||
@@ -729,6 +784,7 @@ TEST_F(WebServerPrometheusDisabledTest, rejectedIfPrometheusIsDisabled)
|
||||
|
||||
TEST_F(WebServerPrometheusTest, validResponse)
|
||||
{
|
||||
auto cache = MockLedgerCache();
|
||||
uint32_t const webServerPort = tests::util::generateFreePort();
|
||||
auto& testCounter = PrometheusService::counterInt("test_counter", util::prometheus::Labels());
|
||||
++testCounter;
|
||||
@@ -736,7 +792,7 @@ TEST_F(WebServerPrometheusTest, validResponse)
|
||||
ClioConfigDefinition const serverConfig{
|
||||
getParseAdminServerConfig(boost::json::parse(jsonServerConfigWithAdminPassword(webServerPort)))
|
||||
};
|
||||
auto server = makeServerSync(serverConfig, ctx, dosGuard, e);
|
||||
auto server = makeServerSync(serverConfig, ctx, dosGuard, e, cache);
|
||||
auto const [status, res] = HttpSyncClient::get(
|
||||
"localhost",
|
||||
std::to_string(webServerPort),
|
||||
|
||||
Reference in New Issue
Block a user