Expand description
ajj: A JSON-RPC router inspired by axum’s Router
.
This crate provides a way to define a JSON-RPC router that can be used to
route requests to handlers. It is inspired by the axum
crate’s
axum::Router
.
§Basic usage
The Router
type is the main type provided by this crate. It is used to
register JSON-RPC methods and their handlers.
use ajj::{Router, HandlerCtx, ResponsePayload};
// Provide methods called "double" and "add" to the router.
let router = Router::<u64>::new()
.route("add", |params: u64, state: u64| async move {
Ok::<_, ()>(params + state)
})
.with_state(3u64)
.route("double", |params: u64| async move {
Ok::<_, ()>(params * 2)
})
// Routes get a ctx, which can be used to send notifications.
.route("notify", |ctx: HandlerCtx| async move {
if ctx.notifications().is_none() {
// This error will appear in the ResponsePayload's `data` field.
return Err("notifications are disabled");
}
let req_id = 15u8;
tokio::task::spawn_blocking(move || {
// something expensive goes here
let result = 100_000_000;
let _ = ctx.notify(&serde_json::json!({
"req_id": req_id,
"result": result,
}));
});
Ok(req_id)
})
.route("error_example", || async {
// This will appear in the ResponsePayload's `message` field.
ResponsePayload::<(), ()>::internal_error_message("this is an error".into())
});
§Handlers
Methods are routed via the Handler
trait, which is blanket implemented
for many async functions. Handler
contain implement the logic executed
when calling methods on the JSON-RPC router.
Handlers can return either
Result<T, E> where T: Serialize, E: Serialize
ResponsePayload<T, E> where T: Serialize, E: Serialize
These types will be serialized into the JSON-RPC response. The T
type
represents the result of the method, and the E
type represents an error
response. The E
type is optional, and can be set to ()
if no error
response is needed.
See the Handler
trait docs for more information.
§Serving the Router
We recommend axum
for serving the router over HTTP. When the "axum"
feature flag is enabled, The Router
provides
Router::into_axum(path: &str)
to instantiate a new axum::Router
, and
register the router to handle requests. You can then serve the
axum::Router
as normal, or add additional routes to it.
// Instantiate a new axum router, and register the JSON-RPC router to handle
// requests at the `/rpc` path, and serve it on port 3000.
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(listener, router.into_axum("/rpc")).await.unwrap();
Routers can also be served over axum websockets. When both axum
and
pubsub
features are enabled, the pubsub
module provides
pubsub::AxumWsCfg
and the pubsub::ajj_websocket
axum handler. This
handler will serve the router over websockets at a specific route. The
router is a property of the AxumWsCfg
object, and is passed to the
handler via axum’s State
extractor.
// The config object contains the tokio runtime handle, and the
// notification buffer size.
let cfg = AxumWsCfg::new(router);
axum
.route("/ws", axum::routing::any(ajj_websocket))
.with_state(cfg)
For IPC and non-axum WebSocket connections, the pubsub
module provides
implementations of the Connect
trait for std::net::SocketAddr
to
create simple WS servers, and
interprocess::local_socket::ListenerOptions
to create simple IPC
servers. We generally recommend using axum
for WebSocket connections, as
it provides a more complete and robust implementation, however, users
needing additional control, or wanting to avoid the axum
dependency
can use the pubsub
module directly.
// Serve the router over websockets on port 3000.
let addr = std::net::SocketAddr::from(([0, 0, 0, 0], 3000));
// The shutdown object will stop the server when dropped.
let shutdown = addr.serve(router).await.unwrap();
See the pubsub
module documentation for more information.
Re-exports§
pub use tower;
pub use serde_json;
Modules§
Structs§
- Batch
Future - A collection of
RouteFuture
s that are executed concurrently. - Error
Payload - A JSON-RPC 2.0 error object.
- Handler
Args - Arguments passed to a handler.
- Handler
Ctx - A context for handler requests that allow the handler to send notifications and spawn long-running tasks (e.g. subscriptions).
- Method
Id - A unique internal identifier for a method.
- Params
- Hint type for differentiating certain handler impls. See the
Handler
trait “Handler argument type inference” section for more information. - RawValue
- Re-export of the
serde_json
crate, primarily to provide theRawValue
type. Reference to a range of bytes encompassing a single valid JSON value in the input data. - Route
Future - A future produced by the
Router
. - Router
- A JSON-RPC router. This is the top-level type for handling JSON-RPC
requests. It is heavily inspired by the
axum::Router
type. - State
- Hint type for differentiating certain handler impls. See the
Handler
trait “Handler argument type inference” section for more information.
Enums§
- Notify
Error - Errors that can occur when sending notifications.
- Registration
Error - Errors that can occur when registering a method.
- Response
Payload - A JSON-RPC 2.0 response payload.
Traits§
- Borrowed
RpcObject - An object that can be both sent and received over RPC, borrowing from the the deserialization context.
- Handler
- A trait describing handlers for JSON-RPC methods.
- RpcBorrow
- An object that can be received over RPC, borrowing from the the deserialization context.
- RpcObject
- An object that can be both sent and received over RPC.
- RpcRecv
- An object that can be received over RPC.
- RpcSend
- An object that can be sent over RPC.