turul-rpc-server 0.1.0

Async JSON-RPC 2.0 dispatcher, handler trait, and session context for turul-rpc.
Documentation

turul-rpc-server

Async JSON-RPC 2.0 dispatcher, handler trait, and session context for the turul-rpc framework.

Built on turul-rpc-core wire types and turul-rpc-jsonrpc codec. Most consumers should depend on the turul-rpc facade, which re-exports this crate's items.

What's here

  • JsonRpcDispatcher<E> — typed dispatcher. Routes incoming requests to registered handlers and converts handler-returned domain errors to JSON-RPC error responses via ToJsonRpcError. Includes handle_batch() for JSON-RPC 2.0 §6 batch dispatch.
  • JsonRpcHandler async trait — your handler returns Result<Value, YourError>. The dispatcher owns wire-format conversion.
  • ToJsonRpcError trait — implement on your domain error type to control how it maps to a JsonRpcErrorObject.
  • SessionContext — opaque session info passed through to handlers (id, metadata, type-erased broadcaster, request-scoped extensions).
  • Optional streaming module (feature streams): JsonRpcFrame, StreamingJsonRpcHandler, StreamingJsonRpcDispatcher for progressive responses.

Quick start

use turul_rpc_server::{JsonRpcDispatcher, JsonRpcHandler, SessionContext, ToJsonRpcError};
use turul_rpc_core::error::JsonRpcErrorObject;
use turul_rpc_core::request::RequestParams;
use async_trait::async_trait;
use serde_json::{json, Value};

#[derive(thiserror::Error, Debug)]
#[error("oops: {0}")]
struct MyError(&'static str);

impl ToJsonRpcError for MyError {
    fn to_error_object(&self) -> JsonRpcErrorObject {
        JsonRpcErrorObject::invalid_params(&self.to_string())
    }
}

struct Echo;

#[async_trait]
impl JsonRpcHandler for Echo {
    type Error = MyError;
    async fn handle(
        &self,
        method: &str,
        _params: Option<RequestParams>,
        _session: Option<SessionContext>,
    ) -> Result<Value, MyError> {
        Ok(json!({ "echoed": method }))
    }
}

# async fn run() {
let mut d: JsonRpcDispatcher<MyError> = JsonRpcDispatcher::new();
d.register_method("echo".into(), Echo);

// Handle a batch body. Returns None for all-notifications, otherwise
// the response JSON string.
let _: Option<String> = d.handle_batch(r#"{"jsonrpc":"2.0","method":"echo","id":1}"#).await;
# }

Features

Feature Default Pulls in
async yes async-trait, futures — required for the dispatcher and handler trait
streams no async + the streaming dispatcher

License

Dual-licensed under MIT or Apache-2.0 at your option. See the workspace README for details.