solana_jsonrpc_core/
middleware.rs

1//! `IoHandler` middlewares
2
3use calls::Metadata;
4use types::{Request, Response, Call, Output};
5use futures::{future::Either, Future};
6
7/// RPC middleware
8pub trait Middleware<M: Metadata>: Send + Sync + 'static {
9	/// A returned request future.
10	type Future: Future<Item=Option<Response>, Error=()> + Send + 'static;
11
12	/// A returned call future.
13	type CallFuture: Future<Item=Option<Output>, Error=()> + Send + 'static;
14
15	/// Method invoked on each request.
16	/// Allows you to either respond directly (without executing RPC call)
17	/// or do any additional work before and/or after processing the request.
18	fn on_request<F, X>(&self, request: Request, meta: M, next: F) -> Either<Self::Future, X> where
19		F: FnOnce(Request, M) -> X + Send,
20		X: Future<Item=Option<Response>, Error=()> + Send + 'static,
21	{
22		Either::B(next(request, meta))
23	}
24
25	/// Method invoked on each call inside a request.
26	///
27	/// Allows you to either handle the call directly (without executing RPC call).
28	fn on_call<F, X>(&self, call: Call, meta: M, next: F) -> Either<Self::CallFuture, X> where
29		F: FnOnce(Call, M) -> X + Send,
30		X: Future<Item=Option<Output>, Error=()> + Send + 'static,
31	{
32		Either::B(next(call, meta))
33	}
34}
35
36/// Dummy future used as a noop result of middleware.
37pub type NoopFuture = Box<Future<Item=Option<Response>, Error=()> + Send>;
38/// Dummy future used as a noop call result of middleware.
39pub type NoopCallFuture = Box<Future<Item=Option<Output>, Error=()> + Send>;
40
41/// No-op middleware implementation
42#[derive(Debug, Default)]
43pub struct Noop;
44impl<M: Metadata> Middleware<M> for Noop {
45	type Future = NoopFuture;
46	type CallFuture = NoopCallFuture;
47}
48
49impl<M: Metadata, A: Middleware<M>, B: Middleware<M>>
50	Middleware<M> for (A, B)
51{
52	type Future = Either<A::Future, B::Future>;
53	type CallFuture = Either<A::CallFuture, B::CallFuture>;
54
55	fn on_request<F, X>(&self, request: Request, meta: M, process: F) -> Either<Self::Future, X> where
56		F: FnOnce(Request, M) -> X + Send,
57		X: Future<Item=Option<Response>, Error=()> + Send + 'static,
58	{
59		repack(self.0.on_request(request, meta, move |request, meta| {
60			self.1.on_request(request, meta, process)
61		}))
62	}
63
64	fn on_call<F, X>(&self, call: Call, meta: M, process: F) -> Either<Self::CallFuture, X> where
65		F: FnOnce(Call, M) -> X + Send,
66		X: Future<Item=Option<Output>, Error=()> + Send + 'static,
67	{
68		repack(self.0.on_call(call, meta, move |call, meta| {
69			self.1.on_call(call, meta, process)
70		}))
71	}
72}
73
74impl<M: Metadata, A: Middleware<M>, B: Middleware<M>, C: Middleware<M>>
75	Middleware<M> for (A, B, C)
76{
77	type Future = Either<A::Future, Either<B::Future, C::Future>>;
78	type CallFuture = Either<A::CallFuture, Either<B::CallFuture, C::CallFuture>>;
79
80	fn on_request<F, X>(&self, request: Request, meta: M, process: F) -> Either<Self::Future, X> where
81		F: FnOnce(Request, M) -> X + Send,
82		X: Future<Item=Option<Response>, Error=()> + Send + 'static,
83	{
84		repack(self.0.on_request(request, meta, move |request, meta| {
85			repack(self.1.on_request(request, meta, move |request, meta| {
86				self.2.on_request(request, meta, process)
87			}))
88		}))
89	}
90
91	fn on_call<F, X>(&self, call: Call, meta: M, process: F) -> Either<Self::CallFuture, X> where
92		F: FnOnce(Call, M) -> X + Send,
93		X: Future<Item=Option<Output>, Error=()> + Send + 'static,
94	{
95		repack(self.0.on_call(call, meta, move |call, meta| {
96			repack(self.1.on_call(call, meta, move |call, meta| {
97				self.2.on_call(call, meta, process)
98			}))
99		}))
100	}
101}
102
103impl<M: Metadata, A: Middleware<M>, B: Middleware<M>, C: Middleware<M>, D: Middleware<M>>
104	Middleware<M> for (A, B, C, D)
105{
106	type Future = Either<A::Future, Either<B::Future, Either<C::Future, D::Future>>>;
107	type CallFuture = Either<A::CallFuture, Either<B::CallFuture, Either<C::CallFuture, D::CallFuture>>>;
108
109	fn on_request<F, X>(&self, request: Request, meta: M, process: F) -> Either<Self::Future, X> where
110		F: FnOnce(Request, M) -> X + Send,
111		X: Future<Item=Option<Response>, Error=()> + Send + 'static,
112	{
113		repack(self.0.on_request(request, meta, move |request, meta| {
114			repack(self.1.on_request(request, meta, move |request, meta| {
115				repack(self.2.on_request(request, meta, move |request, meta| {
116					self.3.on_request(request, meta, process)
117				}))
118			}))
119		}))
120	}
121
122	fn on_call<F, X>(&self, call: Call, meta: M, process: F) -> Either<Self::CallFuture, X> where
123		F: FnOnce(Call, M) -> X + Send,
124		X: Future<Item=Option<Output>, Error=()> + Send + 'static,
125	{
126		repack(self.0.on_call(call, meta, move |call, meta| {
127			repack(self.1.on_call(call, meta, move |call, meta| {
128				repack(self.2.on_call(call, meta, move |call, meta| {
129					self.3.on_call(call, meta, process)
130				}))
131			}))
132		}))
133	}
134}
135
136#[inline(always)]
137fn repack<A, B, X>(result: Either<A, Either<B, X>>) -> Either<Either<A, B>, X> {
138	match result {
139		Either::A(a) => Either::A(Either::A(a)),
140		Either::B(Either::A(b)) => Either::A(Either::B(b)),
141		Either::B(Either::B(x)) => Either::B(x),
142	}
143}