pub struct ServerBuilder<HttpMiddleware, RpcMiddleware> { /* private fields */ }Expand description
Builder to configure and create a JSON-RPC server.
Implementations§
Source§impl Builder<Identity, Identity>
impl Builder<Identity, Identity>
Sourcepub fn with_config(config: ServerConfig) -> Self
pub fn with_config(config: ServerConfig) -> Self
Create a server builder with the given ServerConfig.
Source§impl<HttpMiddleware, RpcMiddleware> Builder<HttpMiddleware, RpcMiddleware>
impl<HttpMiddleware, RpcMiddleware> Builder<HttpMiddleware, RpcMiddleware>
Sourcepub fn set_config(self, cfg: ServerConfig) -> Self
pub fn set_config(self, cfg: ServerConfig) -> Self
Configure the ServerConfig.
Sourcepub fn set_rpc_middleware<T>(
self,
rpc_middleware: RpcServiceBuilder<T>,
) -> Builder<HttpMiddleware, T>
pub fn set_rpc_middleware<T>( self, rpc_middleware: RpcServiceBuilder<T>, ) -> Builder<HttpMiddleware, T>
Enable middleware that is invoked on every JSON-RPC call.
The middleware itself is very similar to the tower middleware but
it has a different service trait which takes &self instead &mut self
which means that you can’t use built-in middleware from tower.
Another consequence of &self is that you must wrap any of the middleware state in
a type which is Send and provides interior mutability such as Arc<Mutex>.
The builder itself exposes a similar API as the [tower::ServiceBuilder]
where it is possible to compose layers to the middleware.
To add middleware RpcServiceBuilder exposes a few different layer APIs that
are wrapped on top of the [tower::ServiceBuilder].
When the server is started these layers are wrapped in the RpcService and
that’s why the service APIs is not exposed.
use std::{
net::SocketAddr,
sync::{
atomic::{AtomicUsize, Ordering},
Arc,
},
time::Instant,
};
use jsonrpsee_server::{
middleware::rpc::{
Batch, MethodResponse, Notification, Request, RpcService, RpcServiceBuilder,
RpcServiceT,
},
ServerBuilder,
};
#[derive(Clone)]
struct MyMiddleware<S> {
service: S,
count: Arc<AtomicUsize>,
}
impl<S> RpcServiceT for MyMiddleware<S>
where
S: RpcServiceT + Clone + Send + Sync + 'static,
{
fn call<'a>(&self, req: Request<'a>) -> impl Future<Output = MethodResponse> + Send + 'a {
tracing::info!("MyMiddleware processed call {}", req.method);
let count = self.count.clone();
let service = self.service.clone();
async move {
let rp = service.call(req).await;
// Modify the state.
count.fetch_add(1, Ordering::Relaxed);
rp
}
}
fn batch<'a>(&self, batch: Batch<'a>) -> impl Future<Output = MethodResponse> + Send + 'a {
self.service.batch(batch)
}
fn notification<'a>(
&self,
notif: Notification<'a>,
) -> impl Future<Output = MethodResponse> + Send + 'a {
self.service.notification(notif)
}
}
// Create a state per connection
// NOTE: The service type can be omitted once `start` is called on the server.
let m = RpcServiceBuilder::new().layer_fn(move |service: ()| MyMiddleware {
service,
count: Arc::new(AtomicUsize::new(0)),
});
let builder = ServerBuilder::default().set_rpc_middleware(m);Sourcepub fn set_http_middleware<T>(
self,
http_middleware: ServiceBuilder<T>,
) -> Builder<T, RpcMiddleware>
pub fn set_http_middleware<T>( self, http_middleware: ServiceBuilder<T>, ) -> Builder<T, RpcMiddleware>
Configure a custom [tower::ServiceBuilder] middleware for composing layers to be applied
to the RPC service.
Default: No tower layers are applied to the RPC service.
§Examples
use std::{net::SocketAddr, time::Duration};
#[tokio::main]
async fn main() {
let builder = tower::ServiceBuilder::new().timeout(Duration::from_secs(2));
let server = jsonrpsee_server::ServerBuilder::new()
.set_http_middleware(builder)
.build("127.0.0.1:0".parse::<SocketAddr>().unwrap())
.await
.unwrap();
}Sourcepub async fn build(
self,
addrs: impl ToSocketAddrs,
) -> Result<Server<HttpMiddleware, RpcMiddleware>>
pub async fn build( self, addrs: impl ToSocketAddrs, ) -> Result<Server<HttpMiddleware, RpcMiddleware>>
Finalize the configuration of the server. Consumes the Builder.
#[tokio::main]
async fn main() {
let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
let occupied_addr = listener.local_addr().unwrap();
let addrs: &[std::net::SocketAddr] = &[occupied_addr, "127.0.0.1:0".parse().unwrap()];
assert!(jsonrpsee_server::ServerBuilder::default().build(occupied_addr).await.is_err());
assert!(jsonrpsee_server::ServerBuilder::default().build(addrs).await.is_ok());
}Trait Implementations§
Auto Trait Implementations§
impl<HttpMiddleware, RpcMiddleware> !RefUnwindSafe for Builder<HttpMiddleware, RpcMiddleware>
impl<HttpMiddleware, RpcMiddleware> !UnwindSafe for Builder<HttpMiddleware, RpcMiddleware>
impl<HttpMiddleware, RpcMiddleware> Freeze for Builder<HttpMiddleware, RpcMiddleware>
impl<HttpMiddleware, RpcMiddleware> Send for Builder<HttpMiddleware, RpcMiddleware>
impl<HttpMiddleware, RpcMiddleware> Sync for Builder<HttpMiddleware, RpcMiddleware>
impl<HttpMiddleware, RpcMiddleware> Unpin for Builder<HttpMiddleware, RpcMiddleware>
impl<HttpMiddleware, RpcMiddleware> UnsafeUnpin for Builder<HttpMiddleware, RpcMiddleware>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
impl<T> Read<Exclusive, BecauseExclusive> for Twhere
T: ?Sized,
§impl<T> WithSubscriber for T
impl<T> WithSubscriber for T
§fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘwhere
S: Into<Dispatch>,
fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘwhere
S: Into<Dispatch>,
§fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ
fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ
Layout§
Note: Unable to compute type layout, possibly due to this type having generic parameters. Layout can only be computed for concrete, fully-instantiated types.