#json-rpc #json-rpc-server #server-client #rpc-server #protocols #server-side #client-side

nanorpc

JSON-RPC 2.0子集,具有神奇的自动生成服务器和客户端功能

10个版本

0.1.13 2024年8月23日
0.1.12 2022年10月30日
0.1.7 2022年9月17日
0.1.3 2022年8月31日

#1552网络编程

Download history 280/week @ 2024-05-03 244/week @ 2024-05-10 180/week @ 2024-05-17 157/week @ 2024-05-24 136/week @ 2024-05-31 90/week @ 2024-06-07 147/week @ 2024-06-14 170/week @ 2024-06-21 124/week @ 2024-06-28 172/week @ 2024-07-05 179/week @ 2024-07-12 187/week @ 2024-07-19 291/week @ 2024-07-26 191/week @ 2024-08-02 305/week @ 2024-08-09 330/week @ 2024-08-16

1,148 每月下载量
23 个包中使用了(17个直接使用)

ISC 许可证

21KB
334

nanorpc:JSON-RPC 2.0子集的魔法库(WIP)

动机

通常,编写客户端-服务器网络API(例如,REST API)涉及以下三个步骤

  • 用英语指定协议
  • 实现协议的服务器端
  • 分别实现协议的客户端

这很麻烦,而且容易出错。协议实际上在三个不同的地方和以三种不同的方式指定了三次,并且保持它们同步是一项巨大的工作。

相反,我们希望一次指定协议,然后自动拥有

  • 一个服务器实现,泛型
    • 每个端点的业务逻辑
    • 低级网络细节(例如,“在此HTTP端点监听”)
  • 一个客户端实现,泛型于低级网络细节(例如,“调用此HTTP端点”)
  • 充分利用Rust的类型系统,以帮助避免序列化和反序列化不匹配、打字错误等问题。

关于 nanorpc

nanorpc 确实做到了。它是一个带有宏 #[nanorpc_derive] 的JSON-RPC子集实现,该宏给定表示API接口的trait,抽象出实现API的所有 重复 部分。

特别是

  • nanorpc 定义了动态类型的JSON-RPC服务器和客户端trait
    • 一个 RpcService trait,用于描述JSON-RPC服务器端响应者(给定JSON请求,生成JSON响应)
    • 一个 RpcTransport trait,用于描述JSON-RPC客户端请求者(给定JSON请求,与某人交谈以生成JSON响应)
  • 给定描述RPC方法、它们的参数类型和它们的返回类型的 FooProtocol trait,[nanorpc_derive] 继承
    • 一个名为 FooService 的结构体,它可以将任何实现 FooProtocol 的“业务逻辑”结构体包装成一个实现了 RpcService 的结构体。
    • 一个名为 FooClient 的结构体,它可以将任何实现 RpcTransport 的 JSON 传输包装成一个具有对应 RPC 方法的结构体。

例如

#[nanorpc_derive]
#[async_trait]
pub trait MathProtocol {
    /// Adds two numbers. Arguments and return type must be JSON-serializable through `serde_json`
    async fn add(&self, x: f64, y: f64) -> f64;
    /// Multiplies two numbers
    async fn mult(&self, x: f64, y: f64) -> f64;
}

// Autogenerates a server struct:
pub struct MathService<T: MathProtocol>(pub T);

#[async_trait]
impl <T: MathService> RpcService for MathService<T> {
    //...
}

// Autogenerates a client struct like:
pub struct MathClient<T: RpcTransport>(pub T);

impl <T: RpcTransport> MathClient {
    /// Adds two numbers
    pub async fn add(&self, x: f64, y: f64) -> Result<f64, T::Error>;

    //...
}

在 JSON 层面上,上述协议将响应 JSON-RPC 2.0 请求

{"jsonrpc": "2.0", "method": "mult", "params": [42, 23], "id": 1}

如下

{"jsonrpc": "2.0", "result": 966, "id": 1}

依赖

~2-3MB
~63K SLoC