From 4c34e40a4c03654f28564d39319ee8ee4aac263f Mon Sep 17 00:00:00 2001 From: Birk Tjelmeland Date: Mon, 26 Aug 2024 17:02:33 +0200 Subject: [PATCH] feat(types): add `lenient` feature The `lenient` feature allows for parsing `Request`s and `Notification`s that doesn't have `jsonrpc` fields. This is useful for interacting with some implementations that are not completely standards-conforming. --- jsonrpsee/Cargo.toml | 1 + jsonrpsee/src/lib.rs | 1 + types/Cargo.toml | 3 +++ types/src/request.rs | 12 ++++++++++++ 4 files changed, 17 insertions(+) diff --git a/jsonrpsee/Cargo.toml b/jsonrpsee/Cargo.toml index 5211011d3d..3351b7cec5 100644 --- a/jsonrpsee/Cargo.toml +++ b/jsonrpsee/Cargo.toml @@ -37,6 +37,7 @@ http-client = ["jsonrpsee-http-client", "jsonrpsee-types", "jsonrpsee-core/clien wasm-client = ["jsonrpsee-wasm-client", "jsonrpsee-types", "jsonrpsee-core/client"] ws-client = ["jsonrpsee-ws-client", "jsonrpsee-types", "jsonrpsee-core/client"] macros = ["jsonrpsee-proc-macros", "jsonrpsee-types", "tracing"] +lenient = ["jsonrpsee-types/lenient"] client = ["http-client", "ws-client", "wasm-client", "client-ws-transport-tls", "client-web-transport", "async-client", "async-wasm-client", "client-core"] client-core = ["jsonrpsee-core/client"] diff --git a/jsonrpsee/src/lib.rs b/jsonrpsee/src/lib.rs index 3df36e5c8f..b485d6be26 100644 --- a/jsonrpsee/src/lib.rs +++ b/jsonrpsee/src/lib.rs @@ -48,6 +48,7 @@ //! - **`client-ws-transport`** - Enables `ws` transport with TLS. //! - **`client-ws-transport-no-tls`** - Enables `ws` transport without TLS. //! - **`client-web-transport`** - Enables `websys` transport. +//! - **`lenient`** - Enables lenient request parsing, allowing requests without a `jsonrpc` field. #![warn(missing_docs, missing_debug_implementations, missing_copy_implementations, unreachable_pub)] #![cfg_attr(not(test), warn(unused_crate_dependencies))] diff --git a/types/Cargo.toml b/types/Cargo.toml index 62039633b2..a3de1f3edf 100644 --- a/types/Cargo.toml +++ b/types/Cargo.toml @@ -18,3 +18,6 @@ serde = { version = "1", default-features = false, features = ["derive"] } serde_json = { version = "1", default-features = false, features = ["alloc", "raw_value", "std"] } thiserror = "1.0" http = "1" + +[features] +lenient = [] diff --git a/types/src/request.rs b/types/src/request.rs index 28026a0392..262bfd300d 100644 --- a/types/src/request.rs +++ b/types/src/request.rs @@ -41,6 +41,7 @@ use serde_json::value::RawValue; #[derive(Serialize, Deserialize, Debug, Clone)] pub struct Request<'a> { /// JSON-RPC version. + #[cfg_attr(feature = "lenient", serde(default))] pub jsonrpc: TwoPointZero, /// Request ID #[serde(borrow)] @@ -101,6 +102,7 @@ pub struct InvalidRequest<'a> { #[derive(Serialize, Deserialize, Debug, Clone)] pub struct Notification<'a, T> { /// JSON-RPC version. + #[cfg_attr(feature = "lenient", serde(default))] pub jsonrpc: TwoPointZero, /// Name of the method to be invoked. #[serde(borrow)] @@ -240,6 +242,16 @@ mod test { assert!(serde_json::from_str::(ser).is_err()); } + #[test] + fn deserialize_missing_jsonrpc_field() { + let ser = r#"{"method":"say_hello","params":[],"id":1}"#; + #[cfg(feature = "lenient")] + assert!(serde_json::from_str::(ser).is_ok()); + + #[cfg(not(feature = "lenient"))] + assert!(serde_json::from_str::(ser).is_err()); + } + #[test] fn deserialize_invalid_request() { let s = r#"{"id":120,"method":"my_method","params":["foo", "bar"],"extra_field":[]}"#;