cuprate-hinto-janai/rpc/interface/src/router_builder.rs

193 lines
10 KiB
Rust
Raw Normal View History

rpc: impl `cuprate-rpc-interface` (#233) * fixed-bytes: add `serde`, document feature flags * fixed-bytes: add derives * rpc: add `as _` syntax to macro * rpc: use `ByteArrayVec` and `ContainerAsBlob` for binary types * fixed-bytes: re-add derives * rpc-types: dedup default value within macro * readme: fixed bytes section * types: custom epee - `BlockCompleteEntry` * types: custom epee - `KeyImageSpentStatus` * types: custom epee - `PoolInfoExtent` * types: add `Status::Other(String)` variant * types: custom epee - `TxEntry`, add `read_epee_field` macro * bin: custom epee - `GetBlocks` * types: add `serde.rs` * misc: make `TxEntry` an `enum`, impl serde * misc: `unimplemented!()` for `TxEntry`'s epee * types: add `BlockCompleteEntry` * rpc: replace `BlockCompleteEntry` with `cuprate-types` * types: document `BlockCompleteEntry` * bin: fix `number_of_fields` for `GetBlocksResponse` * misc: add `Distribution` * distribution: add todo * misc fixes * readme: add `(De)serialization invariants` * distribution: compress variants * types: add `block_complete_entry.rs` * net: fix imports * p2p: fix imports * turn off default-features * p2p: fix imports * misc fixes * Update net/wire/Cargo.toml Co-authored-by: Boog900 <boog900@tutanota.com> * distribution: module doc * wire: re-export types * test-utils: add `crate::rpc::types` module * test-utils: conditional json doc-tests * bin: use enum for `GetBlocksResponse` * misc: use lowercase for stringify * json: add test data, fix macro doc tests * json: add all data * other: add all data * bin: add skeleton * docs * move type to correct file * remove duplicated fields for custom epee * rpc: `client/{client,constants}.rs` -> `client.rs` * lib.rs: remove `clippy::module_inception` * macros: add json doc test macro * json: add some tests * json: add doc-test for all types * add all other JSON doc-tests * move doc-test macros to files * base: add doc-tests * rpc: add `cuprate-rpc-interface` skeleton files * traits * json_rpc_method: add `.is_restricted()` * add route fn signatures * types: add rpc enums * interface: routes, types * interface: simplify routes * rewrite interface fns * types: remove `()` type alias, add `(restricted)` * types: add `other::InPeers` * interface: routes * types: fix `is_restricted()` * interface: reorder short-circuit bool * clean up traits/bounds * types: remove `axum` feature * interface: cleanup unused imports * interface: call handler in routes * json: TODO distribution test * interface: readme intro * combine `RpcHandler` + `RpcService`, add `RpcDummyHandler` * interface: readme docs + test * `IsRestricted` -> `RpcCall` * fix no input route problem * interface: `RpcHandlerDummy` docs * interface: crate docs * replace `create_router` with `RouterBuilder` * types: docs * types: doc `JsonRpc{Request,Response}` * types: readme docs * interface: doc `route/` * interface: fix `todo!()` * interface: allow customizing HTTP method on route functions * interface: fix tests * fix derives * Update rpc/interface/README.md Co-authored-by: Boog900 <boog900@tutanota.com> * Update rpc/interface/README.md Co-authored-by: Boog900 <boog900@tutanota.com> * interface: make `RpcHandler`'s `Future` generic * interface: add JSON-RPC notification todo * formatting * interface: use associated type bound for `RpcHandler`'s `Future` --------- Co-authored-by: Boog900 <boog900@tutanota.com>
2024-08-05 23:50:38 +00:00
//! Free functions.
//---------------------------------------------------------------------------------------------------- Use
use axum::Router;
rpc: impl `cuprate-rpc-interface` (#233) * fixed-bytes: add `serde`, document feature flags * fixed-bytes: add derives * rpc: add `as _` syntax to macro * rpc: use `ByteArrayVec` and `ContainerAsBlob` for binary types * fixed-bytes: re-add derives * rpc-types: dedup default value within macro * readme: fixed bytes section * types: custom epee - `BlockCompleteEntry` * types: custom epee - `KeyImageSpentStatus` * types: custom epee - `PoolInfoExtent` * types: add `Status::Other(String)` variant * types: custom epee - `TxEntry`, add `read_epee_field` macro * bin: custom epee - `GetBlocks` * types: add `serde.rs` * misc: make `TxEntry` an `enum`, impl serde * misc: `unimplemented!()` for `TxEntry`'s epee * types: add `BlockCompleteEntry` * rpc: replace `BlockCompleteEntry` with `cuprate-types` * types: document `BlockCompleteEntry` * bin: fix `number_of_fields` for `GetBlocksResponse` * misc: add `Distribution` * distribution: add todo * misc fixes * readme: add `(De)serialization invariants` * distribution: compress variants * types: add `block_complete_entry.rs` * net: fix imports * p2p: fix imports * turn off default-features * p2p: fix imports * misc fixes * Update net/wire/Cargo.toml Co-authored-by: Boog900 <boog900@tutanota.com> * distribution: module doc * wire: re-export types * test-utils: add `crate::rpc::types` module * test-utils: conditional json doc-tests * bin: use enum for `GetBlocksResponse` * misc: use lowercase for stringify * json: add test data, fix macro doc tests * json: add all data * other: add all data * bin: add skeleton * docs * move type to correct file * remove duplicated fields for custom epee * rpc: `client/{client,constants}.rs` -> `client.rs` * lib.rs: remove `clippy::module_inception` * macros: add json doc test macro * json: add some tests * json: add doc-test for all types * add all other JSON doc-tests * move doc-test macros to files * base: add doc-tests * rpc: add `cuprate-rpc-interface` skeleton files * traits * json_rpc_method: add `.is_restricted()` * add route fn signatures * types: add rpc enums * interface: routes, types * interface: simplify routes * rewrite interface fns * types: remove `()` type alias, add `(restricted)` * types: add `other::InPeers` * interface: routes * types: fix `is_restricted()` * interface: reorder short-circuit bool * clean up traits/bounds * types: remove `axum` feature * interface: cleanup unused imports * interface: call handler in routes * json: TODO distribution test * interface: readme intro * combine `RpcHandler` + `RpcService`, add `RpcDummyHandler` * interface: readme docs + test * `IsRestricted` -> `RpcCall` * fix no input route problem * interface: `RpcHandlerDummy` docs * interface: crate docs * replace `create_router` with `RouterBuilder` * types: docs * types: doc `JsonRpc{Request,Response}` * types: readme docs * interface: doc `route/` * interface: fix `todo!()` * interface: allow customizing HTTP method on route functions * interface: fix tests * fix derives * Update rpc/interface/README.md Co-authored-by: Boog900 <boog900@tutanota.com> * Update rpc/interface/README.md Co-authored-by: Boog900 <boog900@tutanota.com> * interface: make `RpcHandler`'s `Future` generic * interface: add JSON-RPC notification todo * formatting * interface: use associated type bound for `RpcHandler`'s `Future` --------- Co-authored-by: Boog900 <boog900@tutanota.com>
2024-08-05 23:50:38 +00:00
use crate::{
route::{bin, fallback, json_rpc, other},
rpc_handler::RpcHandler,
};
//---------------------------------------------------------------------------------------------------- RouterBuilder
/// Generate the `RouterBuilder` struct.
macro_rules! generate_router_builder {
($(
// Syntax:
// $BUILDER_FUNCTION_NAME =>
// $ACTUAL_ENDPOINT_STRING =>
// $ENDPOINT_FUNCTION_MODULE::$ENDPOINT_FUNCTION =>
// ($HTTP_METHOD(s))
$endpoint_ident:ident =>
$endpoint_string:literal =>
$endpoint_module:ident::$endpoint_fn:ident =>
($($http_method:ident),*)
),* $(,)?) => {
/// Builder for creating the RPC router.
///
/// This builder allows you to selectively enable endpoints for the router,
/// and a [`fallback`](RouterBuilder::fallback) route.
///
/// The [`default`](RouterBuilder::default) is to enable [`all`](RouterBuilder::all) routes.
///
/// # Routes
/// Functions that enable routes are separated into 3 groups:
/// - `json_rpc` (enables all of JSON RPC 2.0)
/// - `other_` (e.g. [`other_get_height`](RouterBuilder::other_get_height))
/// - `bin_` (e.g. [`bin_get_blocks`](RouterBuilder::bin_get_blocks))
///
/// For a list of all `monerod` routes, see
/// [here](https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.h#L97-L189),
/// or the source file of this type.
///
/// # Aliases
/// Some routes have aliases, such as [`/get_height`](RouterBuilder::other_get_height)
/// and [`/getheight`](RouterBuilder::other_getheight).
///
/// These both route to the same handler function, but they do not enable each other.
///
/// If desired, you can enable `/get_height` but not `/getheight`.
///
/// # Example
/// ```rust
/// use cuprate_rpc_interface::{RouterBuilder, RpcHandlerDummy};
///
/// // Create a router with _only_ `/json_rpc` enabled.
/// let only_json_rpc = RouterBuilder::<RpcHandlerDummy>::new()
/// .json_rpc()
/// .build();
///
/// // Create a router with:
/// // - `/get_outs.bin` enabled
/// // - A fallback enabled
/// let get_outs_bin_and_fallback = RouterBuilder::<RpcHandlerDummy>::new()
/// .bin_get_outs()
/// .fallback()
/// .build();
///
/// // Create a router with all endpoints enabled.
/// let all = RouterBuilder::<RpcHandlerDummy>::new()
/// .all()
/// .build();
/// ```
#[derive(Clone)]
pub struct RouterBuilder<H: RpcHandler> {
router: Router<H>,
}
impl<H: RpcHandler> RouterBuilder<H> {
/// Create a new [`Self`].
#[must_use]
pub fn new() -> Self {
Self {
router: Router::new(),
}
}
/// Build [`Self`] into a [`Router`].
///
/// All endpoints enabled in [`RouterBuilder`]
/// will be enabled in this [`Router`].
pub fn build(self) -> Router<H> {
self.router
}
/// Enable all endpoints, including [`Self::fallback`].
#[must_use]
pub fn all(mut self) -> Self {
$(
self = self.$endpoint_ident();
)*
self.fallback()
}
/// Enable the catch-all fallback route.
///
/// Any unknown or disabled route will route here, e.g.:
/// - `get_info`
/// - `getinfo`
/// - `asdf`
#[must_use]
pub fn fallback(self) -> Self {
Self {
router: self.router.fallback(fallback::fallback),
}
}
$(
#[doc = concat!(
"Enable the `",
$endpoint_string,
"` endpoint.",
)]
#[must_use]
pub fn $endpoint_ident(self) -> Self {
Self {
router: self.router.route(
$endpoint_string,
::axum::routing::method_routing::MethodRouter::new()
$(.$http_method($endpoint_module::$endpoint_fn::<H>))*
),
}
}
)*
}
};
}
generate_router_builder! {
// JSON-RPC 2.0 route.
json_rpc => "/json_rpc" => json_rpc::json_rpc => (get, post),
// Other JSON routes.
other_get_height => "/get_height" => other::get_height => (get, post),
other_getheight => "/getheight" => other::get_height => (get, post),
other_get_transactions => "/get_transactions" => other::get_transactions => (get, post),
other_gettransactions => "/gettransactions" => other::get_transactions => (get, post),
other_get_alt_blocks_hashes => "/get_alt_blocks_hashes" => other::get_alt_blocks_hashes => (get, post),
other_is_key_image_spent => "/is_key_image_spent" => other::is_key_image_spent => (get, post),
other_send_raw_transaction => "/send_raw_transaction" => other::send_raw_transaction => (get, post),
other_sendrawtransaction => "/sendrawtransaction" => other::send_raw_transaction => (get, post),
other_start_mining => "/start_mining" => other::start_mining => (get, post),
other_stop_mining => "/stop_mining" => other::stop_mining => (get, post),
other_mining_status => "/mining_status" => other::mining_status => (get, post),
other_save_bc => "/save_bc" => other::save_bc => (get, post),
other_get_peer_list => "/get_peer_list" => other::get_peer_list => (get, post),
other_get_public_nodes => "/get_public_nodes" => other::get_public_nodes => (get, post),
other_set_log_hash_rate => "/set_log_hash_rate" => other::set_log_hash_rate => (get, post),
other_set_log_level => "/set_log_level" => other::set_log_level => (get, post),
other_set_log_categories => "/set_log_categories" => other::set_log_categories => (get, post),
other_get_transaction_pool => "/get_transaction_pool" => other::get_transaction_pool => (get, post),
other_get_transaction_pool_hashes => "/get_transaction_pool_hashes" => other::get_transaction_pool_hashes => (get, post),
other_get_transaction_pool_stats => "/get_transaction_pool_stats" => other::get_transaction_pool_stats => (get, post),
other_set_bootstrap_daemon => "/set_bootstrap_daemon" => other::set_bootstrap_daemon => (get, post),
other_stop_daemon => "/stop_daemon" => other::stop_daemon => (get, post),
other_get_net_stats => "/get_net_stats" => other::get_net_stats => (get, post),
other_get_limit => "/get_limit" => other::get_limit => (get, post),
other_set_limit => "/set_limit" => other::set_limit => (get, post),
other_out_peers => "/out_peers" => other::out_peers => (get, post),
other_in_peers => "/in_peers" => other::in_peers => (get, post),
other_get_outs => "/get_outs" => other::get_outs => (get, post),
other_update => "/update" => other::update => (get, post),
other_pop_blocks => "/pop_blocks" => other::pop_blocks => (get, post),
// Binary routes.
bin_get_blocks => "/get_blocks.bin" => bin::get_blocks => (get, post),
bin_getblocks => "/getblocks.bin" => bin::get_blocks => (get, post),
bin_get_blocks_by_height => "/get_blocks_by_height.bin" => bin::get_blocks_by_height => (get, post),
bin_getblocks_by_height => "/getblocks_by_height.bin" => bin::get_blocks_by_height => (get, post),
bin_get_hashes => "/get_hashes.bin" => bin::get_hashes => (get, post),
bin_gethashes => "/gethashes.bin" => bin::get_hashes => (get, post),
bin_get_o_indexes => "/get_o_indexes.bin" => bin::get_o_indexes => (get, post),
bin_get_outs => "/get_outs.bin" => bin::get_outs => (get, post),
bin_get_transaction_pool_hashes => "/get_transaction_pool_hashes.bin" => bin::get_transaction_pool_hashes => (get, post),
bin_get_output_distribution => "/get_output_distribution.bin" => bin::get_output_distribution => (get, post),
}
impl<H: RpcHandler> Default for RouterBuilder<H> {
/// Uses [`Self::all`].
fn default() -> Self {
Self::new().all()
}
}