Struct ServerBuilder
pub struct ServerBuilder<HttpMiddleware, RpcMiddleware> { /* private fields */ }
Expand description
Builder to configure and create a JSON-RPC server
Implementations§
§impl<HttpMiddleware, RpcMiddleware> Builder<HttpMiddleware, RpcMiddleware>
impl<HttpMiddleware, RpcMiddleware> Builder<HttpMiddleware, RpcMiddleware>
pub fn max_request_body_size(
self,
size: u32,
) -> Builder<HttpMiddleware, RpcMiddleware>
pub fn max_request_body_size( self, size: u32, ) -> Builder<HttpMiddleware, RpcMiddleware>
Set the maximum size of a request body in bytes. Default is 10 MiB.
pub fn max_response_body_size(
self,
size: u32,
) -> Builder<HttpMiddleware, RpcMiddleware>
pub fn max_response_body_size( self, size: u32, ) -> Builder<HttpMiddleware, RpcMiddleware>
Set the maximum size of a response body in bytes. Default is 10 MiB.
pub fn max_connections(self, max: u32) -> Builder<HttpMiddleware, RpcMiddleware>
pub fn max_connections(self, max: u32) -> Builder<HttpMiddleware, RpcMiddleware>
Set the maximum number of connections allowed. Default is 100.
pub fn set_batch_request_config(
self,
cfg: BatchRequestConfig,
) -> Builder<HttpMiddleware, RpcMiddleware>
pub fn set_batch_request_config( self, cfg: BatchRequestConfig, ) -> Builder<HttpMiddleware, RpcMiddleware>
Configure how batch requests shall be handled by the server.
Default: batch requests are allowed and can be arbitrary big but the maximum payload size is limited.
pub fn max_subscriptions_per_connection(
self,
max: u32,
) -> Builder<HttpMiddleware, RpcMiddleware>
pub fn max_subscriptions_per_connection( self, max: u32, ) -> Builder<HttpMiddleware, RpcMiddleware>
Set the maximum number of connections allowed. Default is 1024.
pub 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 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 a middleware [crate::middleware::rpc::RpcServiceBuilder
] exposes a few different layer APIs that
is wrapped on top of the [tower::ServiceBuilder
].
When the server is started these layers are wrapped in the [crate::middleware::rpc::RpcService
] and
that’s why the service APIs is not exposed.
use std::{time::Instant, net::SocketAddr, sync::Arc};
use std::sync::atomic::{Ordering, AtomicUsize};
use jsonrpsee_server::middleware::rpc::{RpcServiceT, RpcService, RpcServiceBuilder};
use jsonrpsee_server::{ServerBuilder, MethodResponse};
use jsonrpsee_core::async_trait;
use jsonrpsee_types::Request;
use futures_util::future::BoxFuture;
#[derive(Clone)]
struct MyMiddleware<S> {
service: S,
count: Arc<AtomicUsize>,
}
impl<'a, S> RpcServiceT<'a> for MyMiddleware<S>
where S: RpcServiceT<'a> + Send + Sync + Clone + 'static,
{
type Future = BoxFuture<'a, MethodResponse>;
fn call(&self, req: Request<'a>) -> Self::Future {
tracing::info!("MyMiddleware processed call {}", req.method);
let count = self.count.clone();
let service = self.service.clone();
Box::pin(async move {
let rp = service.call(req).await;
// Modify the state.
count.fetch_add(1, Ordering::Relaxed);
rp
})
}
}
// 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);
pub fn custom_tokio_runtime(
self,
rt: Handle,
) -> Builder<HttpMiddleware, RpcMiddleware>
pub fn custom_tokio_runtime( self, rt: Handle, ) -> Builder<HttpMiddleware, RpcMiddleware>
Configure a custom [tokio::runtime::Handle
] to run the server on.
Default: [tokio::spawn
]
pub fn enable_ws_ping(
self,
config: PingConfig,
) -> Builder<HttpMiddleware, RpcMiddleware>
pub fn enable_ws_ping( self, config: PingConfig, ) -> Builder<HttpMiddleware, RpcMiddleware>
Enable WebSocket ping/pong on the server.
Default: pings are disabled.
§Examples
use std::{time::Duration, num::NonZeroUsize};
use jsonrpsee_server::{ServerBuilder, PingConfig};
// Set the ping interval to 10 seconds but terminates the connection if a client is inactive for more than 2 minutes
let ping_cfg = PingConfig::new().ping_interval(Duration::from_secs(10)).inactive_limit(Duration::from_secs(60 * 2));
let builder = ServerBuilder::default().enable_ws_ping(ping_cfg);
pub fn disable_ws_ping(self) -> Builder<HttpMiddleware, RpcMiddleware>
pub fn disable_ws_ping(self) -> Builder<HttpMiddleware, RpcMiddleware>
Disable WebSocket ping/pong on the server.
Default: pings are disabled.
pub fn set_id_provider<I>(
self,
id_provider: I,
) -> Builder<HttpMiddleware, RpcMiddleware>where
I: IdProvider + 'static,
pub fn set_id_provider<I>(
self,
id_provider: I,
) -> Builder<HttpMiddleware, RpcMiddleware>where
I: IdProvider + 'static,
Configure custom subscription ID
provider for the server to use
to when getting new subscription calls.
You may choose static dispatch or dynamic dispatch because
IdProvider
is implemented for Box<T>
.
Default: [RandomIntegerIdProvider
].
§Examples
use jsonrpsee_server::{ServerBuilder, RandomStringIdProvider, IdProvider};
// static dispatch
let builder1 = ServerBuilder::default().set_id_provider(RandomStringIdProvider::new(16));
// or dynamic dispatch
let builder2 = ServerBuilder::default().set_id_provider(Box::new(RandomStringIdProvider::new(16)));
pub 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::time::Duration;
use std::net::SocketAddr;
#[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();
}
pub fn set_tcp_no_delay(
self,
no_delay: bool,
) -> Builder<HttpMiddleware, RpcMiddleware>
pub fn set_tcp_no_delay( self, no_delay: bool, ) -> Builder<HttpMiddleware, RpcMiddleware>
Configure TCP_NODELAY
on the socket to the supplied value nodelay
.
Default is true
.
pub fn http_only(self) -> Builder<HttpMiddleware, RpcMiddleware>
pub fn http_only(self) -> Builder<HttpMiddleware, RpcMiddleware>
Configure the server to only serve JSON-RPC HTTP requests.
Default: both http and ws are enabled.
pub fn ws_only(self) -> Builder<HttpMiddleware, RpcMiddleware>
pub fn ws_only(self) -> Builder<HttpMiddleware, RpcMiddleware>
Configure the server to only serve JSON-RPC WebSocket requests.
That implies that server just denies HTTP requests which isn’t a WebSocket upgrade request
Default: both http and ws are enabled.
pub fn set_message_buffer_capacity(
self,
c: u32,
) -> Builder<HttpMiddleware, RpcMiddleware>
pub fn set_message_buffer_capacity( self, c: u32, ) -> Builder<HttpMiddleware, RpcMiddleware>
The server enforces backpressure which means that
n
messages can be buffered and if the client
can’t keep with up the server.
This capacity
is applied per connection and
applies globally on the connection which implies
all JSON-RPC messages.
For example if a subscription produces plenty of new items and the client can’t keep up then no new messages are handled.
If this limit is exceeded then the server will “back-off” and only accept new messages once the client reads pending messages.
§Panics
Panics if the buffer capacity is 0.
pub fn to_service_builder(
self,
) -> TowerServiceBuilder<RpcMiddleware, HttpMiddleware>
pub fn to_service_builder( self, ) -> TowerServiceBuilder<RpcMiddleware, HttpMiddleware>
Convert the server builder to a [TowerServiceBuilder
].
This can be used to utilize the [TowerService
] from jsonrpsee.
§Examples
use jsonrpsee_server::{Methods, ServerHandle, ws, stop_channel, serve_with_graceful_shutdown};
use tower::Service;
use std::{error::Error as StdError, net::SocketAddr};
use futures_util::future::{self, Either};
use hyper_util::rt::{TokioIo, TokioExecutor};
fn run_server() -> ServerHandle {
let (stop_handle, server_handle) = stop_channel();
let svc_builder = jsonrpsee_server::Server::builder().max_connections(33).to_service_builder();
let methods = Methods::new();
let stop_handle = stop_handle.clone();
tokio::spawn(async move {
let listener = tokio::net::TcpListener::bind(SocketAddr::from(([127, 0, 0, 1], 0))).await.unwrap();
loop {
// The `tokio::select!` macro is used to wait for either of the
// listeners to accept a new connection or for the server to be
// stopped.
let (sock, remote_addr) = tokio::select! {
res = listener.accept() => {
match res {
Ok(sock) => sock,
Err(e) => {
tracing::error!("failed to accept v4 connection: {:?}", e);
continue;
}
}
}
_ = stop_handle.clone().shutdown() => break,
};
let stop_handle2 = stop_handle.clone();
let svc_builder2 = svc_builder.clone();
let methods2 = methods.clone();
let svc = tower::service_fn(move |req| {
let stop_handle = stop_handle2.clone();
let svc_builder = svc_builder2.clone();
let methods = methods2.clone();
let mut svc = svc_builder.build(methods, stop_handle.clone());
// It's not possible to know whether the websocket upgrade handshake failed or not here.
let is_websocket = ws::is_upgrade_request(&req);
if is_websocket {
println!("websocket")
} else {
println!("http")
}
// Call the jsonrpsee service which
// may upgrade it to a WebSocket connection
// or treat it as "ordinary HTTP request".
async move { svc.call(req).await }
});
// Upgrade the connection to a HTTP service with graceful shutdown.
tokio::spawn(serve_with_graceful_shutdown(sock, svc, stop_handle.clone().shutdown()));
}
});
server_handle
}
pub async fn build(
self,
addrs: impl ToSocketAddrs,
) -> Result<Server<HttpMiddleware, RpcMiddleware>, Error>
pub async fn build( self, addrs: impl ToSocketAddrs, ) -> Result<Server<HttpMiddleware, RpcMiddleware>, Error>
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());
}
pub fn build_from_tcp(
self,
listener: impl Into<TcpListener>,
) -> Result<Server<HttpMiddleware, RpcMiddleware>, Error>
pub fn build_from_tcp( self, listener: impl Into<TcpListener>, ) -> Result<Server<HttpMiddleware, RpcMiddleware>, Error>
Finalizes the configuration of the server with customized TCP settings on the socket.
use jsonrpsee_server::Server;
use socket2::{Domain, Socket, Type};
use std::time::Duration;
#[tokio::main]
async fn main() {
let addr = "127.0.0.1:0".parse().unwrap();
let domain = Domain::for_address(addr);
let socket = Socket::new(domain, Type::STREAM, None).unwrap();
socket.set_nonblocking(true).unwrap();
let address = addr.into();
socket.bind(&address).unwrap();
socket.listen(4096).unwrap();
let server = Server::builder().build_from_tcp(socket).unwrap();
}
Trait Implementations§
Auto Trait Implementations§
impl<HttpMiddleware, RpcMiddleware> Freeze for Builder<HttpMiddleware, RpcMiddleware>
impl<HttpMiddleware, RpcMiddleware> !RefUnwindSafe 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> !UnwindSafe 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<T> Conv for T
impl<T> Conv for T
§impl<T> FmtForward for T
impl<T> FmtForward for T
§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self
to use its Binary
implementation when Debug
-formatted.§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self
to use its Display
implementation when
Debug
-formatted.§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self
to use its LowerExp
implementation when
Debug
-formatted.§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self
to use its LowerHex
implementation when
Debug
-formatted.§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self
to use its Octal
implementation when Debug
-formatted.§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self
to use its Pointer
implementation when
Debug
-formatted.§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self
to use its UpperExp
implementation when
Debug
-formatted.§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self
to use its UpperHex
implementation when
Debug
-formatted.§fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read more§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self
and passes that borrow into the pipe function. Read more§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self
and passes that borrow into the pipe function. Read more§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self
, then passes self.as_ref()
into the pipe function.§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self
, then passes self.as_mut()
into the pipe
function.§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self
, then passes self.deref()
into the pipe function.§impl<T> Pointable for T
impl<T> Pointable for T
§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
§impl<T> Tap for T
impl<T> Tap for T
§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B>
of a value. Read more§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B>
of a value. Read more§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R>
view of a value. Read more§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R>
view of a value. Read more§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target
of a value. Read more§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target
of a value. Read more§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap()
only in debug builds, and is erased in release builds.§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut()
only in debug builds, and is erased in release
builds.§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow()
only in debug builds, and is erased in release
builds.§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut()
only in debug builds, and is erased in release
builds.§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref()
only in debug builds, and is erased in release
builds.§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut()
only in debug builds, and is erased in release
builds.§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref()
only in debug builds, and is erased in release
builds.§impl<T> TryConv for T
impl<T> TryConv for T
§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>
Source§impl<T> WithSubscriber for T
impl<T> WithSubscriber for T
Source§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>,
Source§fn with_current_subscriber(self) -> WithDispatch<Self>
fn with_current_subscriber(self) -> WithDispatch<Self>
impl<T> ErasedDestructor for Twhere
T: 'static,
impl<T> MaybeDebug for Twhere
T: Debug,
impl<T> MaybeSend for Twhere
T: Send,
impl<T> MaybeSendSync for T
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.