cuprate_rpc_interface/router_builder.rs
1//! Free functions.
2
3//---------------------------------------------------------------------------------------------------- Use
4use axum::Router;
5
6use crate::{
7 route::{bin, fallback, json_rpc, other},
8 rpc_handler::RpcHandler,
9};
10
11//---------------------------------------------------------------------------------------------------- RouterBuilder
12/// Generate the `RouterBuilder` struct.
13macro_rules! generate_router_builder {
14 ($(
15 // Syntax:
16 // $BUILDER_FUNCTION_NAME =>
17 // $ACTUAL_ENDPOINT_STRING =>
18 // $ENDPOINT_FUNCTION_MODULE::$ENDPOINT_FUNCTION =>
19 // ($HTTP_METHOD(s))
20 $endpoint_ident:ident =>
21 $endpoint_string:literal =>
22 $endpoint_module:ident::$endpoint_fn:ident =>
23 ($($http_method:ident),*)
24 ),* $(,)?) => {
25 /// Builder for creating the RPC router.
26 ///
27 /// This builder allows you to selectively enable endpoints for the router,
28 /// and a [`fallback`](RouterBuilder::fallback) route.
29 ///
30 /// The [`default`](RouterBuilder::default) is to enable [`all`](RouterBuilder::all) routes.
31 ///
32 /// # Routes
33 /// Functions that enable routes are separated into 3 groups:
34 /// - `json_rpc` (enables all of JSON RPC 2.0)
35 /// - `other_` (e.g. [`other_get_height`](RouterBuilder::other_get_height))
36 /// - `bin_` (e.g. [`bin_get_blocks`](RouterBuilder::bin_get_blocks))
37 ///
38 /// For a list of all `monerod` routes, see
39 /// [here](https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.h#L97-L189),
40 /// or the source file of this type.
41 ///
42 /// # Aliases
43 /// Some routes have aliases, such as [`/get_height`](RouterBuilder::other_get_height)
44 /// and [`/getheight`](RouterBuilder::other_getheight).
45 ///
46 /// These both route to the same handler function, but they do not enable each other.
47 ///
48 /// If desired, you can enable `/get_height` but not `/getheight`.
49 ///
50 /// # Example
51 /// ```rust
52 /// use cuprate_rpc_interface::{RouterBuilder, RpcHandlerDummy};
53 ///
54 /// // Create a router with _only_ `/json_rpc` enabled.
55 /// let only_json_rpc = RouterBuilder::<RpcHandlerDummy>::new()
56 /// .json_rpc()
57 /// .build();
58 ///
59 /// // Create a router with:
60 /// // - `/get_outs.bin` enabled
61 /// // - A fallback enabled
62 /// let get_outs_bin_and_fallback = RouterBuilder::<RpcHandlerDummy>::new()
63 /// .bin_get_outs()
64 /// .fallback()
65 /// .build();
66 ///
67 /// // Create a router with all endpoints enabled.
68 /// let all = RouterBuilder::<RpcHandlerDummy>::new()
69 /// .all()
70 /// .build();
71 /// ```
72 #[derive(Clone)]
73 pub struct RouterBuilder<H: RpcHandler> {
74 router: Router<H>,
75 }
76
77 impl<H: RpcHandler> RouterBuilder<H> {
78 /// Create a new [`Self`].
79 #[must_use]
80 pub fn new() -> Self {
81 Self {
82 router: Router::new(),
83 }
84 }
85
86 /// Build [`Self`] into a [`Router`].
87 ///
88 /// All endpoints enabled in [`RouterBuilder`]
89 /// will be enabled in this [`Router`].
90 pub fn build(self) -> Router<H> {
91 self.router
92 }
93
94 /// Enable all endpoints, including [`Self::fallback`].
95 #[must_use]
96 pub fn all(mut self) -> Self {
97 $(
98 self = self.$endpoint_ident();
99 )*
100
101 self.fallback()
102 }
103
104 /// Enable the catch-all fallback route.
105 ///
106 /// Any unknown or disabled route will route here, e.g.:
107 /// - `get_info`
108 /// - `getinfo`
109 /// - `asdf`
110 #[must_use]
111 pub fn fallback(self) -> Self {
112 Self {
113 router: self.router.fallback(fallback::fallback),
114 }
115 }
116
117 $(
118 #[doc = concat!(
119 "Enable the `",
120 $endpoint_string,
121 "` endpoint.",
122 )]
123 #[must_use]
124 pub fn $endpoint_ident(self) -> Self {
125 Self {
126 router: self.router.route(
127 $endpoint_string,
128 ::axum::routing::method_routing::MethodRouter::new()
129 $(.$http_method($endpoint_module::$endpoint_fn::<H>))*
130 ),
131 }
132 }
133 )*
134 }
135 };
136}
137
138generate_router_builder! {
139 // JSON-RPC 2.0 route.
140 json_rpc => "/json_rpc" => json_rpc::json_rpc => (get, post),
141
142 // Other JSON routes.
143 other_get_height => "/get_height" => other::get_height => (get, post),
144 other_getheight => "/getheight" => other::get_height => (get, post),
145 other_get_transactions => "/get_transactions" => other::get_transactions => (get, post),
146 other_gettransactions => "/gettransactions" => other::get_transactions => (get, post),
147 other_get_alt_blocks_hashes => "/get_alt_blocks_hashes" => other::get_alt_blocks_hashes => (get, post),
148 other_is_key_image_spent => "/is_key_image_spent" => other::is_key_image_spent => (get, post),
149 other_send_raw_transaction => "/send_raw_transaction" => other::send_raw_transaction => (get, post),
150 other_sendrawtransaction => "/sendrawtransaction" => other::send_raw_transaction => (get, post),
151 other_start_mining => "/start_mining" => other::start_mining => (get, post),
152 other_stop_mining => "/stop_mining" => other::stop_mining => (get, post),
153 other_mining_status => "/mining_status" => other::mining_status => (get, post),
154 other_save_bc => "/save_bc" => other::save_bc => (get, post),
155 other_get_peer_list => "/get_peer_list" => other::get_peer_list => (get, post),
156 other_get_public_nodes => "/get_public_nodes" => other::get_public_nodes => (get, post),
157 other_set_log_hash_rate => "/set_log_hash_rate" => other::set_log_hash_rate => (get, post),
158 other_set_log_level => "/set_log_level" => other::set_log_level => (get, post),
159 other_set_log_categories => "/set_log_categories" => other::set_log_categories => (get, post),
160 other_get_transaction_pool => "/get_transaction_pool" => other::get_transaction_pool => (get, post),
161 other_get_transaction_pool_hashes => "/get_transaction_pool_hashes" => other::get_transaction_pool_hashes => (get, post),
162 other_get_transaction_pool_stats => "/get_transaction_pool_stats" => other::get_transaction_pool_stats => (get, post),
163 other_set_bootstrap_daemon => "/set_bootstrap_daemon" => other::set_bootstrap_daemon => (get, post),
164 other_stop_daemon => "/stop_daemon" => other::stop_daemon => (get, post),
165 other_get_net_stats => "/get_net_stats" => other::get_net_stats => (get, post),
166 other_get_limit => "/get_limit" => other::get_limit => (get, post),
167 other_set_limit => "/set_limit" => other::set_limit => (get, post),
168 other_out_peers => "/out_peers" => other::out_peers => (get, post),
169 other_in_peers => "/in_peers" => other::in_peers => (get, post),
170 other_get_outs => "/get_outs" => other::get_outs => (get, post),
171 other_update => "/update" => other::update => (get, post),
172 other_pop_blocks => "/pop_blocks" => other::pop_blocks => (get, post),
173
174 // Binary routes.
175 bin_get_blocks => "/get_blocks.bin" => bin::get_blocks => (get, post),
176 bin_getblocks => "/getblocks.bin" => bin::get_blocks => (get, post),
177 bin_get_blocks_by_height => "/get_blocks_by_height.bin" => bin::get_blocks_by_height => (get, post),
178 bin_getblocks_by_height => "/getblocks_by_height.bin" => bin::get_blocks_by_height => (get, post),
179 bin_get_hashes => "/get_hashes.bin" => bin::get_hashes => (get, post),
180 bin_gethashes => "/gethashes.bin" => bin::get_hashes => (get, post),
181 bin_get_o_indexes => "/get_o_indexes.bin" => bin::get_o_indexes => (get, post),
182 bin_get_outs => "/get_outs.bin" => bin::get_outs => (get, post),
183 bin_get_transaction_pool_hashes => "/get_transaction_pool_hashes.bin" => bin::get_transaction_pool_hashes => (get, post),
184 bin_get_output_distribution => "/get_output_distribution.bin" => bin::get_output_distribution => (get, post),
185}
186
187impl<H: RpcHandler> Default for RouterBuilder<H> {
188 /// Uses [`Self::all`].
189 fn default() -> Self {
190 Self::new().all()
191 }
192}