mirror of
https://github.com/XRPLF/clio.git
synced 2025-12-06 17:27:58 +00:00
29
src/rpc/README.md
Normal file
29
src/rpc/README.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# Clio RPC subsystem
|
||||
## Background
|
||||
The RPC subsystem is where the common framework for handling incoming JSON requests is implemented.
|
||||
Currently the NextGen RPC framework is a work in progress and the handlers are not yet implemented using the new common framework classes.
|
||||
|
||||
## Integration plan
|
||||
- Implement base framework - **done**
|
||||
- Migrate handlers one by one, making them injectable, adding unit-tests - **in progress**
|
||||
- Integrate all new handlers into clio in one go
|
||||
- Cover the rest with unit-tests
|
||||
- Release first time with new subsystem active
|
||||
|
||||
## Components
|
||||
See `common` subfolder.
|
||||
|
||||
- **AnyHandler**: The type-erased wrapper that allows for storing different handlers in one map/vector.
|
||||
- **RpcSpec/FieldSpec**: The RPC specification classes, used to specify how incoming JSON is to be validated before it's parsed and passed on to individual handler implementations.
|
||||
- **Validators**: A bunch of supported validators that can be specified as requirements for each **`FieldSpec`** to make up the final **`RpcSpec`** of any given RPC handler.
|
||||
|
||||
## Implementing a (NextGen) handler
|
||||
See `unittests/rpc` for exmaples.
|
||||
|
||||
Handlers need to fulfil the requirements specified by the **`Handler`** concept (see `rpc/common/Concepts.h`):
|
||||
- Expose types:
|
||||
* `Input` - The POD struct which acts as input for the handler
|
||||
* `Output` - The POD struct which acts as output of a valid handler invocation
|
||||
- Have a `spec()` member function returning a const reference to an **`RpcSpec`** describing the JSON input.
|
||||
- Have a `process(Input)` member function that operates on `Input` POD and returns `HandlerReturnType<Output>`
|
||||
- Implement `value_from` and `value_to` support using `tag_invoke` as per `boost::json` documentation for these functions.
|
||||
@@ -27,10 +27,23 @@ namespace RPCng {
|
||||
|
||||
/**
|
||||
* @brief A type-erased Handler that can contain any (NextGen) RPC handler class
|
||||
*
|
||||
* This allows to store different handlers in one map/vector etc.
|
||||
* Support for copying was added in order to allow storing in a
|
||||
* map/unordered_map using the initializer_list constructor.
|
||||
*/
|
||||
class AnyHandler final
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Type-erases any handler class.
|
||||
*
|
||||
* @tparam HandlerType The real type of wrapped handler class
|
||||
* @tparam ProcessingStrategy A strategy that implements how processing of
|
||||
* JSON is to be done
|
||||
* @param handler The handler to wrap. Required to fulfil the @ref Handler
|
||||
* concept.
|
||||
*/
|
||||
template <
|
||||
Handler HandlerType,
|
||||
typename ProcessingStrategy = detail::DefaultProcessor<HandlerType>>
|
||||
@@ -55,6 +68,12 @@ public:
|
||||
AnyHandler&
|
||||
operator=(AnyHandler&&) = default;
|
||||
|
||||
/**
|
||||
* @brief Process incoming JSON by the stored handler
|
||||
*
|
||||
* @param value The JSON to process
|
||||
* @return JSON result or @ref RPC::Status on error
|
||||
*/
|
||||
[[nodiscard]] ReturnType
|
||||
process(boost::json::value const& value) const
|
||||
{
|
||||
|
||||
@@ -33,6 +33,14 @@ namespace RPCng {
|
||||
*/
|
||||
struct FieldSpec final
|
||||
{
|
||||
/**
|
||||
* @brief Construct a field specification out of a set of requirements
|
||||
*
|
||||
* @tparam Requirements The types of requirements @ref Requirement
|
||||
* @param key The key in a JSON object that the field validates
|
||||
* @param requirements The requirements, each of them have to fulfil
|
||||
* the @ref Requirement concept
|
||||
*/
|
||||
template <Requirement... Requirements>
|
||||
FieldSpec(std::string const& key, Requirements&&... requirements)
|
||||
: validator_{detail::makeFieldValidator<Requirements...>(
|
||||
@@ -41,6 +49,12 @@ struct FieldSpec final
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Validates the passed JSON value using the stored requirements
|
||||
*
|
||||
* @param value The JSON value to validate
|
||||
* @return Nothing on success; @ref RPC::Status on error
|
||||
*/
|
||||
[[nodiscard]] MaybeError
|
||||
validate(boost::json::value const& value) const;
|
||||
|
||||
@@ -56,10 +70,21 @@ private:
|
||||
*/
|
||||
struct RpcSpec final
|
||||
{
|
||||
/**
|
||||
* @brief Construct a full RPC request specification
|
||||
*
|
||||
* @param fields The fields of the RPC specification @ref FieldSpec
|
||||
*/
|
||||
RpcSpec(std::initializer_list<FieldSpec> fields) : fields_{fields}
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Validates the passed JSON value using the stored field specs
|
||||
*
|
||||
* @param value The JSON value to validate
|
||||
* @return Nothing on success; @ref RPC::Status on error
|
||||
*/
|
||||
[[nodiscard]] MaybeError
|
||||
validate(boost::json::value const& value) const;
|
||||
|
||||
|
||||
@@ -76,10 +76,22 @@ class Section final
|
||||
std::vector<FieldSpec> specs;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Construct new section validator from a list of specs
|
||||
*
|
||||
* @param specs List of specs @ref FieldSpec
|
||||
*/
|
||||
explicit Section(std::initializer_list<FieldSpec> specs) : specs{specs}
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Verify that the JSON value representing the section is valid
|
||||
* according to the given specs
|
||||
*
|
||||
* @param value The JSON value representing the outer object
|
||||
* @param key The key used to retrieve the section from the outer object
|
||||
*/
|
||||
[[nodiscard]] MaybeError
|
||||
verify(boost::json::value const& value, std::string_view key) const;
|
||||
};
|
||||
@@ -99,6 +111,13 @@ struct Required final
|
||||
template <typename... Types>
|
||||
struct Type final
|
||||
{
|
||||
/**
|
||||
* @brief Verify that the JSON value is (one) of specified type(s)
|
||||
*
|
||||
* @param value The JSON value representing the outer object
|
||||
* @param key The key used to retrieve the tested value from the outer
|
||||
* object
|
||||
*/
|
||||
[[nodiscard]] MaybeError
|
||||
verify(boost::json::value const& value, std::string_view key) const
|
||||
{
|
||||
@@ -126,10 +145,23 @@ class Between final
|
||||
Type max_;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Construct the validator storing min and max values
|
||||
*
|
||||
* @param min
|
||||
* @param max
|
||||
*/
|
||||
explicit Between(Type min, Type max) : min_{min}, max_{max}
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Verify that the JSON value is within a certain range
|
||||
*
|
||||
* @param value The JSON value representing the outer object
|
||||
* @param key The key used to retrieve the tested value from the outer
|
||||
* object
|
||||
*/
|
||||
[[nodiscard]] MaybeError
|
||||
verify(boost::json::value const& value, std::string_view key) const
|
||||
{
|
||||
@@ -157,10 +189,22 @@ class EqualTo final
|
||||
Type original_;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Construct the validator with stored original value
|
||||
*
|
||||
* @param original The original value to store
|
||||
*/
|
||||
explicit EqualTo(Type original) : original_{original}
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Verify that the JSON value is equal to the stored original
|
||||
*
|
||||
* @param value The JSON value representing the outer object
|
||||
* @param key The key used to retrieve the tested value from the outer
|
||||
* object
|
||||
*/
|
||||
[[nodiscard]] MaybeError
|
||||
verify(boost::json::value const& value, std::string_view key) const
|
||||
{
|
||||
@@ -192,10 +236,22 @@ class OneOf final
|
||||
std::vector<Type> options_;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Construct the validator with stored options
|
||||
*
|
||||
* @param options The list of allowed options
|
||||
*/
|
||||
explicit OneOf(std::initializer_list<Type> options) : options_{options}
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Verify that the JSON value is one of the stored options
|
||||
*
|
||||
* @param value The JSON value representing the outer object
|
||||
* @param key The key used to retrieve the tested value from the outer
|
||||
* object
|
||||
*/
|
||||
[[nodiscard]] MaybeError
|
||||
verify(boost::json::value const& value, std::string_view key) const
|
||||
{
|
||||
@@ -229,11 +285,25 @@ class ValidateArrayAt final
|
||||
std::vector<FieldSpec> specs_;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Constructs a validator that validates the specified element of a
|
||||
* JSON array
|
||||
*
|
||||
* @param idx The index inside the array to validate
|
||||
* @param specs The specifications to validate against
|
||||
*/
|
||||
ValidateArrayAt(std::size_t idx, std::initializer_list<FieldSpec> specs)
|
||||
: idx_{idx}, specs_{specs}
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Verify that the JSON array element at given index is valid
|
||||
* according the stored specs
|
||||
*
|
||||
* @param value The JSON value representing the outer object
|
||||
* @param key The key used to retrieve the array from the outer object
|
||||
*/
|
||||
[[nodiscard]] MaybeError
|
||||
verify(boost::json::value const& value, std::string_view key) const;
|
||||
};
|
||||
@@ -247,11 +317,25 @@ class CustomValidator final
|
||||
validator_;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Constructs a custom validator from any supported callable
|
||||
*
|
||||
* @tparam Fn The type of callable
|
||||
* @param fn The callable/function object
|
||||
*/
|
||||
template <typename Fn>
|
||||
explicit CustomValidator(Fn&& fn) : validator_{std::forward<Fn>(fn)}
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Verify that the JSON value is valid according to the custom
|
||||
* validation function stored
|
||||
*
|
||||
* @param value The JSON value representing the outer object
|
||||
* @param key The key used to retrieve the tested value from the outer
|
||||
* object
|
||||
*/
|
||||
[[nodiscard]] MaybeError
|
||||
verify(boost::json::value const& value, std::string_view key) const;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user