rpc_router/router/
router.rs

1use crate::router::router_inner::RouterInner;
2use crate::Resources;
3use crate::{CallResult, Request, ResourcesInner, RouterBuilder};
4use serde_json::Value;
5use std::sync::Arc;
6
7#[derive(Debug, Clone)]
8pub struct Router {
9	inner: Arc<RouterInner>,
10	base_resources: Resources,
11}
12
13//-- Builder
14impl Router {
15	/// Returns a new `ResourcesBuilder`.
16	/// This is equivalent to calling `Resources::default()`.
17	pub fn builder() -> RouterBuilder {
18		RouterBuilder::default()
19	}
20}
21
22// -- Methods
23impl Router {
24	/// Performs the RPC call for a given RpcRequest object (i.e., `.id, .method, .params`)
25	/// with the eventual resources of the router.
26	///
27	/// To add additional resources on top of the router's resources, call `.call_with_resources(request, resources)`
28	///
29	/// - Returns an CallResult that echoes the `id` and `method`, and includes the `Result<Value, rpc_router::Error>` result.
30	///
31	/// - The `rpc_router::Error` includes a variant `rpc_router::Error::Handler(RpcHandlerError)`,
32	///   where `RpcHandlerError` allows retrieval of the application error returned by the handler
33	///   through `RpcHandlerError::get::<T>(&self) -> Option<T>`.
34	///   This mechanism enables application RPC handlers to return specific application errors while still utilizing
35	///   the `rpc-router` result structure, thereby allowing them to retrieve their specific error type.
36	///
37	pub async fn call(&self, rpc_request: Request) -> CallResult {
38		self.inner.call(self.base_resources.clone(), rpc_request).await
39	}
40
41	/// Similar to `.call(...)`, but takes an additional `Resources` parameter that will be overlaid on top
42	/// of the eventual base router resources.
43	///
44	/// Note: The router will first try to get the resource from the overlay, and then,
45	///       will try the base router resources.
46	pub async fn call_with_resources(&self, rpc_request: Request, additional_resources: Resources) -> CallResult {
47		let resources = self.compute_call_resources(additional_resources);
48
49		self.inner.call(resources, rpc_request).await
50	}
51
52	/// Lower level function to `.call` which take all Rpc Request properties as value.
53	/// If id is None, it will be set a Value::Null
54	///
55	/// This also use router base resources.
56	///
57	/// To add additional resources on top of the router's resources, call `.call_route_with_resources(request, resources)`
58	///
59	/// - method: The json-rpc method name.
60	/// -     id: The json-rpc request `.id`, which should be sent by the client.
61	///           It is required to echo it back in the json-rpc response.
62	///           Can be `Value::Null`, and if None, it will be set to `Value::Null`
63	/// - params: The optional json-rpc params
64	///
65	/// Returns an CallResult, where either the success value (CallResponse) or the error (CallError)
66	/// will echo back the `id` and `method` part of their construct
67	pub async fn call_route(&self, id: Option<Value>, method: impl Into<String>, params: Option<Value>) -> CallResult {
68		self.inner.call_route(self.base_resources.clone(), id, method, params).await
69	}
70
71	/// Similar to `.call_route`, but takes an additional `Resources` parameter that will be overlaid on top
72	/// of the eventual base router resources.
73	///
74	/// Note: The router will first try to get the resource from the overlay, and then,
75	///       will try the base router resources.
76	pub async fn call_route_with_resources(
77		&self,
78		id: Option<Value>,
79		method: impl Into<String>,
80		params: Option<Value>,
81		additional_resources: Resources,
82	) -> CallResult {
83		let resources = self.compute_call_resources(additional_resources);
84
85		self.inner.call_route(resources, id, method, params).await
86	}
87}
88
89// Crate only method
90impl Router {
91	/// For specific or advanced use cases.
92	///
93	/// Use `RpcRouterBuilder::default()...build()` if unsure.
94	///
95	/// Creates an `RpcRouter` from its inner data.
96	///
97	/// Note: This is intended for situations where a custom builder
98	///       workflow is needed. The recommended method for creating an `RpcRouter`
99	///       is via the `RpcRouterBuilder`.
100	pub(crate) fn new(inner: RouterInner, resources_inner: ResourcesInner) -> Self {
101		Self {
102			inner: Arc::new(inner),
103			base_resources: Resources::from_base_inner(resources_inner),
104		}
105	}
106
107	pub(crate) fn compute_call_resources(&self, call_resources: Resources) -> Resources {
108		if self.base_resources.is_empty() {
109			call_resources
110		} else {
111			self.base_resources.new_with_overlay(call_resources)
112		}
113	}
114}