feat: Integrate new webserver (#1722)

For #919.
The new web server is not using dosguard yet. It will be fixed by a
separate PR.
This commit is contained in:
Sergey Kuznetsov
2024-11-21 14:48:32 +00:00
committed by GitHub
parent fc3ba07f2e
commit c77154a5e6
90 changed files with 4029 additions and 683 deletions

View File

@@ -25,6 +25,7 @@
#include "rpc/common/Types.hpp"
#include "util/Taggable.hpp"
#include "web/Context.hpp"
#include "web/SubscriptionContextInterface.hpp"
#include <boost/asio/spawn.hpp>
#include <boost/json/array.hpp>
@@ -34,8 +35,8 @@
#include <expected>
#include <functional>
#include <memory>
#include <string>
#include <utility>
using namespace std;
using namespace util;
@@ -46,11 +47,12 @@ std::expected<web::Context, Status>
make_WsContext(
boost::asio::yield_context yc,
boost::json::object const& request,
std::shared_ptr<web::ConnectionBase> const& session,
web::SubscriptionContextPtr session,
util::TagDecoratorFactory const& tagFactory,
data::LedgerRange const& range,
std::string const& clientIp,
std::reference_wrapper<APIVersionParser const> apiVersionParser
std::reference_wrapper<APIVersionParser const> apiVersionParser,
bool isAdmin
)
{
boost::json::value commandValue = nullptr;
@@ -68,7 +70,7 @@ make_WsContext(
return Error{{ClioError::rpcINVALID_API_VERSION, apiVersion.error()}};
auto const command = boost::json::value_to<std::string>(commandValue);
return web::Context(yc, command, *apiVersion, request, session, tagFactory, range, clientIp, session->isAdmin());
return web::Context(yc, command, *apiVersion, request, std::move(session), tagFactory, range, clientIp, isAdmin);
}
std::expected<web::Context, Status>
@@ -94,7 +96,7 @@ make_HttpContext(
auto const command = boost::json::value_to<std::string>(request.at("method"));
if (command == "subscribe" || command == "unsubscribe")
return Error{{RippledError::rpcBAD_SYNTAX, "Subscribe and unsubscribe are only allowed or websocket."}};
return Error{{RippledError::rpcBAD_SYNTAX, "Subscribe and unsubscribe are only allowed for websocket."}};
if (!request.at("params").is_array())
return Error{{ClioError::rpcPARAMS_UNPARSEABLE, "Missing params array."}};

View File

@@ -24,7 +24,7 @@
#include "rpc/common/APIVersion.hpp"
#include "util/Taggable.hpp"
#include "web/Context.hpp"
#include "web/interface/ConnectionBase.hpp"
#include "web/SubscriptionContextInterface.hpp"
#include <boost/asio/spawn.hpp>
#include <boost/json.hpp>
@@ -32,7 +32,6 @@
#include <expected>
#include <functional>
#include <memory>
#include <string>
/*
@@ -49,22 +48,24 @@ namespace rpc {
*
* @param yc The coroutine context
* @param request The request as JSON object
* @param session The connection
* @param session The subscription context
* @param tagFactory A factory that provides tags to track requests
* @param range The ledger range that is available at request time
* @param clientIp The IP address of the connected client
* @param apiVersionParser A parser that is used to parse out the "api_version" field
* @param isAdmin Whether the request has admin privileges
* @return A Websocket context or error Status
*/
std::expected<web::Context, Status>
make_WsContext(
boost::asio::yield_context yc,
boost::json::object const& request,
std::shared_ptr<web::ConnectionBase> const& session,
web::SubscriptionContextPtr session,
util::TagDecoratorFactory const& tagFactory,
data::LedgerRange const& range,
std::string const& clientIp,
std::reference_wrapper<APIVersionParser const> apiVersionParser
std::reference_wrapper<APIVersionParser const> apiVersionParser,
bool isAdmin
);
/**

View File

@@ -20,6 +20,7 @@
#pragma once
#include "rpc/Errors.hpp"
#include "web/SubscriptionContextInterface.hpp"
#include <boost/asio/spawn.hpp>
#include <boost/json/array.hpp>
@@ -32,7 +33,6 @@
#include <cstdint>
#include <expected>
#include <memory>
#include <string>
#include <utility>
#include <variant>
@@ -117,7 +117,7 @@ struct VoidOutput {};
*/
struct Context {
boost::asio::yield_context yield;
std::shared_ptr<web::ConnectionBase> session = {}; // NOLINT(readability-redundant-member-init)
web::SubscriptionContextPtr session = {}; // NOLINT(readability-redundant-member-init)
bool isAdmin = false;
std::string clientIp = {}; // NOLINT(readability-redundant-member-init)
uint32_t apiVersion = 0u; // invalid by default

View File

@@ -22,6 +22,7 @@
#include "data/BackendInterface.hpp"
#include "data/Types.hpp"
#include "feed/SubscriptionManagerInterface.hpp"
#include "feed/Types.hpp"
#include "rpc/Errors.hpp"
#include "rpc/JS.hpp"
#include "rpc/RPCHelpers.hpp"
@@ -114,7 +115,7 @@ SubscribeHandler::process(Input input, Context const& ctx) const
auto output = Output{};
// Mimic rippled. No matter what the request is, the api version changes for the whole session
ctx.session->apiSubVersion = ctx.apiVersion;
ctx.session->setApiSubversion(ctx.apiVersion);
if (input.streams) {
auto const ledger = subscribeToStreams(ctx.yield, *(input.streams), ctx.session);
@@ -138,7 +139,7 @@ boost::json::object
SubscribeHandler::subscribeToStreams(
boost::asio::yield_context yield,
std::vector<std::string> const& streams,
std::shared_ptr<web::ConnectionBase> const& session
feed::SubscriberSharedPtr const& session
) const
{
auto response = boost::json::object{};
@@ -165,7 +166,7 @@ SubscribeHandler::subscribeToStreams(
void
SubscribeHandler::subscribeToAccountsProposed(
std::vector<std::string> const& accounts,
std::shared_ptr<web::ConnectionBase> const& session
feed::SubscriberSharedPtr const& session
) const
{
for (auto const& account : accounts) {
@@ -177,7 +178,7 @@ SubscribeHandler::subscribeToAccountsProposed(
void
SubscribeHandler::subscribeToAccounts(
std::vector<std::string> const& accounts,
std::shared_ptr<web::ConnectionBase> const& session
feed::SubscriberSharedPtr const& session
) const
{
for (auto const& account : accounts) {
@@ -189,7 +190,7 @@ SubscribeHandler::subscribeToAccounts(
void
SubscribeHandler::subscribeToBooks(
std::vector<OrderBook> const& books,
std::shared_ptr<web::ConnectionBase> const& session,
feed::SubscriberSharedPtr const& session,
boost::asio::yield_context yield,
Output& output
) const

View File

@@ -21,6 +21,7 @@
#include "data/BackendInterface.hpp"
#include "feed/SubscriptionManagerInterface.hpp"
#include "feed/Types.hpp"
#include "rpc/common/Specs.hpp"
#include "rpc/common/Types.hpp"
@@ -128,23 +129,20 @@ private:
subscribeToStreams(
boost::asio::yield_context yield,
std::vector<std::string> const& streams,
std::shared_ptr<web::ConnectionBase> const& session
feed::SubscriberSharedPtr const& session
) const;
void
subscribeToAccounts(std::vector<std::string> const& accounts, std::shared_ptr<web::ConnectionBase> const& session)
subscribeToAccounts(std::vector<std::string> const& accounts, feed::SubscriberSharedPtr const& session) const;
void
subscribeToAccountsProposed(std::vector<std::string> const& accounts, feed::SubscriberSharedPtr const& session)
const;
void
subscribeToAccountsProposed(
std::vector<std::string> const& accounts,
std::shared_ptr<web::ConnectionBase> const& session
) const;
void
subscribeToBooks(
std::vector<OrderBook> const& books,
std::shared_ptr<web::ConnectionBase> const& session,
feed::SubscriberSharedPtr const& session,
boost::asio::yield_context yield,
Output& output
) const;

View File

@@ -21,6 +21,7 @@
#include "data/BackendInterface.hpp"
#include "feed/SubscriptionManagerInterface.hpp"
#include "feed/Types.hpp"
#include "rpc/Errors.hpp"
#include "rpc/JS.hpp"
#include "rpc/RPCHelpers.hpp"
@@ -106,10 +107,11 @@ UnsubscribeHandler::process(Input input, Context const& ctx) const
return Output{};
}
void
UnsubscribeHandler::unsubscribeFromStreams(
std::vector<std::string> const& streams,
std::shared_ptr<web::ConnectionBase> const& session
feed::SubscriberSharedPtr const& session
) const
{
for (auto const& stream : streams) {
@@ -130,21 +132,21 @@ UnsubscribeHandler::unsubscribeFromStreams(
}
}
}
void
UnsubscribeHandler::unsubscribeFromAccounts(
std::vector<std::string> accounts,
std::shared_ptr<web::ConnectionBase> const& session
) const
UnsubscribeHandler::unsubscribeFromAccounts(std::vector<std::string> accounts, feed::SubscriberSharedPtr const& session)
const
{
for (auto const& account : accounts) {
auto const accountID = accountFromStringStrict(account);
subscriptions_->unsubAccount(*accountID, session);
}
}
void
UnsubscribeHandler::unsubscribeFromProposedAccounts(
std::vector<std::string> accountsProposed,
std::shared_ptr<web::ConnectionBase> const& session
feed::SubscriberSharedPtr const& session
) const
{
for (auto const& account : accountsProposed) {
@@ -153,10 +155,8 @@ UnsubscribeHandler::unsubscribeFromProposedAccounts(
}
}
void
UnsubscribeHandler::unsubscribeFromBooks(
std::vector<OrderBook> const& books,
std::shared_ptr<web::ConnectionBase> const& session
) const
UnsubscribeHandler::unsubscribeFromBooks(std::vector<OrderBook> const& books, feed::SubscriberSharedPtr const& session)
const
{
for (auto const& orderBook : books) {
subscriptions_->unsubBook(orderBook.book, session);

View File

@@ -21,6 +21,7 @@
#include "data/BackendInterface.hpp"
#include "feed/SubscriptionManagerInterface.hpp"
#include "feed/Types.hpp"
#include "rpc/common/Specs.hpp"
#include "rpc/common/Types.hpp"
@@ -105,22 +106,17 @@ public:
private:
void
unsubscribeFromStreams(std::vector<std::string> const& streams, std::shared_ptr<web::ConnectionBase> const& session)
unsubscribeFromStreams(std::vector<std::string> const& streams, feed::SubscriberSharedPtr const& session) const;
void
unsubscribeFromAccounts(std::vector<std::string> accounts, feed::SubscriberSharedPtr const& session) const;
void
unsubscribeFromProposedAccounts(std::vector<std::string> accountsProposed, feed::SubscriberSharedPtr const& session)
const;
void
unsubscribeFromAccounts(std::vector<std::string> accounts, std::shared_ptr<web::ConnectionBase> const& session)
const;
void
unsubscribeFromProposedAccounts(
std::vector<std::string> accountsProposed,
std::shared_ptr<web::ConnectionBase> const& session
) const;
void
unsubscribeFromBooks(std::vector<OrderBook> const& books, std::shared_ptr<web::ConnectionBase> const& session)
const;
unsubscribeFromBooks(std::vector<OrderBook> const& books, feed::SubscriberSharedPtr const& session) const;
/**
* @brief Convert a JSON object to an Input