JSON RPC
JSON-RPC 2.0 library for C++
dispatcher.cpp
Go to the documentation of this file.
1/**
2 * @file
3 * @brief Implementation of the dispatcher class.
4 */
5
6#include "dispatcher.h"
7#include "dispatcher_p.h"
8#include "exception.h"
9#include "request.h"
10#include "utils.h"
11
12namespace wwa::json_rpc {
13
15
16dispatcher::~dispatcher() = default;
17
18void dispatcher::add_internal_method(std::string_view method, handler_t&& handler)
19{
20 this->d_ptr->add_handler(std::string(method), std::move(handler));
21}
22
23nlohmann::json dispatcher::process_request(const nlohmann::json& request, const std::any& data)
24{
26 if (request.is_array()) {
27 return this->process_batch_request(request, data, unique_id);
28 }
29
30 return this->do_process_request(request, data, false, unique_id);
31}
32
34dispatcher::do_process_request(const nlohmann::json& request, const std::any& data, bool, std::uint64_t unique_id)
35{
36 nlohmann::json discarded = nlohmann::json::value_t::discarded;
37
38 auto request_id = get_request_id(request);
39 bool is_discarded = false;
40 try {
41 const auto req = jsonrpc_request::from_json(request);
42 this->request_parsed(req, data, unique_id);
43 is_discarded = req.id.is_discarded();
44
45 const dispatcher::context_t ctx = std::make_pair(data, req.extra);
46 const auto res = this->invoke(req.method, req.params, ctx, unique_id);
47 if (!request_id.is_null()) {
48 // clang-format off
49 return {
50 {"jsonrpc", "2.0"},
51 {"result", res},
52 {"id", req.id}
53 };
54 // clang-format on
55 }
56
57 return discarded;
58 }
59 catch (const std::exception& e) {
60 this->request_failed(request_id, &e, false, unique_id);
61 const auto* eptr = dynamic_cast<const exception*>(&e);
62 const auto ex = eptr != nullptr ? *eptr : exception(exception::INTERNAL_ERROR, e.what());
63 return is_discarded ? discarded : generate_error_response(ex, request_id);
64 }
65}
66
68dispatcher::process_batch_request(const nlohmann::json& request, const std::any& data, std::uint64_t unique_id)
69{
70 if (request.empty()) {
71 const exception e(exception::INVALID_REQUEST, err_empty_batch);
72 this->request_failed(nullptr, &e, true, unique_id);
73 return generate_error_response(e, nlohmann::json(nullptr));
74 }
75
76 auto response = nlohmann::json::array();
77 for (const auto& req : request) {
78 if (!req.is_object()) {
79 const exception e(exception::INVALID_REQUEST, err_not_jsonrpc_2_0_request);
80 this->request_failed(nullptr, &e, false, unique_id);
81
82 response.push_back(generate_error_response(e, nlohmann::json(nullptr)));
83 }
84 else if (const auto res =
85 this->do_process_request(req, data, true, dispatcher_private::get_and_increment_counter());
86 !res.is_discarded())
87 {
88 response.push_back(res);
89 }
90 }
91
92 return response.empty() ? nlohmann::json(nlohmann::json::value_t::discarded) : response;
93}
94
95void dispatcher::request_parsed(const jsonrpc_request&, const std::any&, std::uint64_t)
96{
97 // Do nothing
98}
99
101 const std::string& method, const nlohmann::json& params, const dispatcher::context_t& ctx, std::uint64_t
102)
103{
104 if (const auto handler = this->d_ptr->find_handler(method); handler != nullptr) {
105 return handler(ctx, params);
106 }
107
109}
110
111void dispatcher::request_failed(const nlohmann::json&, const std::exception*, bool, std::uint64_t)
112{
113 // Do nothing
114}
115
116} // namespace wwa::json_rpc
Private implementation of the JSON RPC dispatcher class.
static std::uint64_t get_and_increment_counter() noexcept
Generates a unique request ID.
A class that manages JSON RPC method handlers and processes JSON RPC requests.
Definition dispatcher.h:77
virtual nlohmann::json do_process_request(const nlohmann::json &request, const std::any &data, bool is_batch, std::uint64_t unique_id)
Processes a single, non-batch JSON RPC request.
virtual void request_parsed(const jsonrpc_request &request, const std::any &data, std::uint64_t unique_id)
Invoked after the request has been parsed.
void add_internal_method(std::string_view method, handler_t &&handler)
Adds a method handler for the specified method.
nlohmann::json process_request(const nlohmann::json &request, const std::any &data={})
Processes a JSON RPC request.
virtual void request_failed(const nlohmann::json &request_id, const std::exception *e, bool is_batch, std::uint64_t unique_id)
Invoked when a request fails.
virtual nlohmann::json invoke(const std::string &method, const nlohmann::json &params, const dispatcher::context_t &ctx, std::uint64_t unique_id)
Invokes a method handler.
virtual nlohmann::json process_batch_request(const nlohmann::json &request, const std::any &data, std::uint64_t unique_id)
Processes a batch request.
dispatcher()
Class constructor.
virtual ~dispatcher()
Class destructor.
JSON RPC Exception class.
Definition exception.h:86
Exception thrown when the method is not found.
Definition exception.h:238
static constexpr int INTERNAL_ERROR
Internal JSON-RPC error.
Definition exception.h:120
static constexpr int INVALID_REQUEST
The JSON sent is not a valid Request object.
Definition exception.h:105
Represents a JSON RPC request.
Definition request.h:22