Skip to content

Commit 4e95f43

Browse files
authored
[types]: ID type instead of serde_json::RawValue (#325)
* get started * add additional test * fix nits * cargo fmt * [types]: write some tests. * [http server]: send empty response on notifs * [http server]: fix tests * [rpc module]: send subscription response * Update types/src/v2/error.rs * fix nits * cargo fmt * Update types/src/v2/params.rs * remove needless clone * remove dead code * [types]: impl PartialEq for JsonErrorObject + test * use beef::Cow * Update http-server/src/tests.rs
1 parent 4f51e2f commit 4e95f43

File tree

17 files changed

+275
-175
lines changed

17 files changed

+275
-175
lines changed

http-client/src/client.rs

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ use crate::traits::Client;
22
use crate::transport::HttpTransportClient;
33
use crate::v2::request::{JsonRpcCallSer, JsonRpcNotificationSer};
44
use crate::v2::{
5-
error::JsonRpcErrorAlloc,
5+
error::JsonRpcError,
66
params::{Id, JsonRpcParams},
77
response::JsonRpcResponse,
88
};
9-
use crate::{Error, JsonRawValue, TEN_MB_SIZE_BYTES};
9+
use crate::{Error, TEN_MB_SIZE_BYTES};
1010
use async_trait::async_trait;
1111
use fnv::FnvHashMap;
1212
use serde::de::DeserializeOwned;
@@ -76,12 +76,12 @@ impl Client for HttpClient {
7676
let response: JsonRpcResponse<_> = match serde_json::from_slice(&body) {
7777
Ok(response) => response,
7878
Err(_) => {
79-
let err: JsonRpcErrorAlloc = serde_json::from_slice(&body).map_err(Error::ParseError)?;
80-
return Err(Error::Request(err));
79+
let err: JsonRpcError = serde_json::from_slice(&body).map_err(Error::ParseError)?;
80+
return Err(Error::Request(err.to_string()));
8181
}
8282
};
8383

84-
let response_id = parse_request_id(response.id)?;
84+
let response_id = response.id.as_number().copied().ok_or(Error::InvalidRequestId)?;
8585

8686
if response_id == id {
8787
Ok(response.result)
@@ -115,15 +115,15 @@ impl Client for HttpClient {
115115
let rps: Vec<JsonRpcResponse<_>> = match serde_json::from_slice(&body) {
116116
Ok(response) => response,
117117
Err(_) => {
118-
let err: JsonRpcErrorAlloc = serde_json::from_slice(&body).map_err(Error::ParseError)?;
119-
return Err(Error::Request(err));
118+
let err: JsonRpcError = serde_json::from_slice(&body).map_err(Error::ParseError)?;
119+
return Err(Error::Request(err.to_string()));
120120
}
121121
};
122122

123123
// NOTE: `R::default` is placeholder and will be replaced in loop below.
124124
let mut responses = vec![R::default(); ordered_requests.len()];
125125
for rp in rps {
126-
let response_id = parse_request_id(rp.id)?;
126+
let response_id = rp.id.as_number().copied().ok_or(Error::InvalidRequestId)?;
127127
let pos = match request_set.get(&response_id) {
128128
Some(pos) => *pos,
129129
None => return Err(Error::InvalidRequestId),
@@ -133,13 +133,3 @@ impl Client for HttpClient {
133133
Ok(responses)
134134
}
135135
}
136-
137-
fn parse_request_id(raw: Option<&JsonRawValue>) -> Result<u64, Error> {
138-
match raw {
139-
None => Err(Error::InvalidRequestId),
140-
Some(id) => {
141-
let id = serde_json::from_str(id.get()).map_err(Error::ParseError)?;
142-
Ok(id)
143-
}
144-
}
145-
}

http-client/src/tests.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::v2::{
2-
error::{JsonRpcErrorCode, JsonRpcErrorObjectAlloc},
2+
error::{JsonRpcError, JsonRpcErrorCode, JsonRpcErrorObject},
33
params::JsonRpcParams,
44
};
55
use crate::{traits::Client, Error, HttpClientBuilder, JsonValue};
@@ -107,9 +107,12 @@ async fn run_request_with_response(response: String) -> Result<JsonValue, Error>
107107
client.request("say_hello", JsonRpcParams::NoParams).await
108108
}
109109

110-
fn assert_jsonrpc_error_response(error: Error, code: JsonRpcErrorObjectAlloc) {
111-
match &error {
112-
Error::Request(e) => assert_eq!(e.error, code),
113-
e => panic!("Expected error: \"{}\", got: {:?}", error, e),
110+
fn assert_jsonrpc_error_response(err: Error, exp: JsonRpcErrorObject) {
111+
match &err {
112+
Error::Request(e) => {
113+
let this: JsonRpcError = serde_json::from_str(&e).unwrap();
114+
assert_eq!(this.error, exp);
115+
}
116+
e => panic!("Expected error: \"{}\", got: {:?}", err, e),
114117
};
115118
}

http-server/src/server.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,9 @@ use hyper::{
3434
Error as HyperError,
3535
};
3636
use jsonrpsee_types::error::{CallError, Error, GenericTransportError};
37-
use jsonrpsee_types::v2::request::{JsonRpcInvalidRequest, JsonRpcRequest};
38-
use jsonrpsee_types::v2::{error::JsonRpcErrorCode, params::RpcParams};
37+
use jsonrpsee_types::v2::error::JsonRpcErrorCode;
38+
use jsonrpsee_types::v2::params::{Id, RpcParams};
39+
use jsonrpsee_types::v2::request::{JsonRpcInvalidRequest, JsonRpcNotification, JsonRpcRequest};
3940
use jsonrpsee_utils::hyper_helpers::read_response_to_body;
4041
use jsonrpsee_utils::server::helpers::{collect_batch_response, send_error};
4142
use jsonrpsee_utils::server::rpc_module::{MethodSink, RpcModule};
@@ -162,7 +163,7 @@ impl Server {
162163
if let Some(method) = methods.get(&*req.method) {
163164
let params = RpcParams::new(req.params.map(|params| params.get()));
164165
// NOTE(niklasad1): connection ID is unused thus hardcoded to `0`.
165-
if let Err(err) = (method)(req.id, params, &tx, 0) {
166+
if let Err(err) = (method)(req.id.clone(), params, &tx, 0) {
166167
log::error!(
167168
"execution of method call '{}' failed: {:?}, request id={:?}",
168169
req.method,
@@ -211,23 +212,27 @@ impl Server {
211212
// Our [issue](https://github.com/paritytech/jsonrpsee/issues/296).
212213
if let Ok(req) = serde_json::from_slice::<JsonRpcRequest>(&body) {
213214
execute(&tx, req);
215+
} else if let Ok(_req) = serde_json::from_slice::<JsonRpcNotification>(&body) {
216+
return Ok::<_, HyperError>(response::ok_response("".into()));
214217
} else if let Ok(batch) = serde_json::from_slice::<Vec<JsonRpcRequest>>(&body) {
215218
if !batch.is_empty() {
216219
single = false;
217220
for req in batch {
218221
execute(&tx, req);
219222
}
220223
} else {
221-
send_error(None, &tx, JsonRpcErrorCode::InvalidRequest.into());
224+
send_error(Id::Null, &tx, JsonRpcErrorCode::InvalidRequest.into());
222225
}
226+
} else if let Ok(_batch) = serde_json::from_slice::<Vec<JsonRpcNotification>>(&body) {
227+
return Ok::<_, HyperError>(response::ok_response("".into()));
223228
} else {
224229
log::error!(
225230
"[service_fn], Cannot parse request body={:?}",
226231
String::from_utf8_lossy(&body[..cmp::min(body.len(), 1024)])
227232
);
228233
let (id, code) = match serde_json::from_slice::<JsonRpcInvalidRequest>(&body) {
229234
Ok(req) => (req.id, JsonRpcErrorCode::InvalidRequest),
230-
Err(_) => (None, JsonRpcErrorCode::ParseError),
235+
Err(_) => (Id::Null, JsonRpcErrorCode::ParseError),
231236
};
232237
send_error(id, &tx, code.into());
233238
}

http-server/src/tests.rs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ async fn invalid_single_method_call() {
8383
let req = r#"{"jsonrpc":"2.0","method":1, "params": "bar"}"#;
8484
let response = http_request(req.into(), uri.clone()).await.unwrap();
8585
assert_eq!(response.status, StatusCode::OK);
86-
assert_eq!(response.body, invalid_request(Id::Null));
86+
assert_eq!(response.body, parse_error(Id::Null));
8787
}
8888

8989
#[tokio::test]
@@ -169,14 +169,11 @@ async fn batched_notifications() {
169169
let addr = server().await;
170170
let uri = to_http_uri(addr);
171171

172-
let req = r#"[
173-
{"jsonrpc": "2.0", "method": "notif", "params": [1,2,4]},
174-
{"jsonrpc": "2.0", "method": "notif", "params": [7]}
175-
]"#;
172+
let req = r#"[{"jsonrpc": "2.0", "method": "notif", "params": [1,2,4]},{"jsonrpc": "2.0", "method": "notif", "params": [7]}]"#;
176173
let response = http_request(req.into(), uri).await.unwrap();
177174
assert_eq!(response.status, StatusCode::OK);
178-
// Note: this is *not* according to spec. Response should be the empty string, `""`.
179-
assert_eq!(response.body, r#"[{"jsonrpc":"2.0","result":"","id":null},{"jsonrpc":"2.0","result":"","id":null}]"#);
175+
// Note: on HTTP acknowledge the notification with an empty response.
176+
assert_eq!(response.body, "");
180177
}
181178

182179
#[tokio::test]
@@ -248,3 +245,14 @@ async fn invalid_request_object() {
248245
assert_eq!(response.status, StatusCode::OK);
249246
assert_eq!(response.body, invalid_request(Id::Num(1)));
250247
}
248+
249+
#[tokio::test]
250+
async fn notif_works() {
251+
let addr = server().await;
252+
let uri = to_http_uri(addr);
253+
254+
let req = r#"{"jsonrpc":"2.0","method":"bar"}"#;
255+
let response = http_request(req.into(), uri).await.unwrap();
256+
assert_eq!(response.status, StatusCode::OK);
257+
assert_eq!(response.body, "");
258+
}

types/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ documentation = "https://docs.rs/jsonrpsee-types"
1111

1212
[dependencies]
1313
async-trait = "0.1"
14-
beef = "0.5"
14+
beef = { version = "0.5", features = ["impl_serde"] }
1515
futures-channel = { version = "0.3", features = ["sink"] }
1616
futures-util = { version = "0.3", default-features = false, features = ["std", "sink", "channel"] }
1717
log = { version = "0.4", default-features = false }

types/src/error.rs

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
use crate::v2::error::JsonRpcErrorAlloc;
21
use std::fmt;
3-
42
/// Convenience type for displaying errors.
53
#[derive(Clone, Debug, PartialEq)]
64
pub struct Mismatch<T> {
@@ -16,10 +14,6 @@ impl<T: fmt::Display> fmt::Display for Mismatch<T> {
1614
}
1715
}
1816

19-
/// Invalid params.
20-
#[derive(Debug)]
21-
pub struct InvalidParams;
22-
2317
/// Error that occurs when a call failed.
2418
#[derive(Debug, thiserror::Error)]
2519
pub enum CallError {
@@ -31,12 +25,6 @@ pub enum CallError {
3125
Failed(#[source] Box<dyn std::error::Error + Send + Sync>),
3226
}
3327

34-
impl From<InvalidParams> for CallError {
35-
fn from(_params: InvalidParams) -> Self {
36-
Self::InvalidParams
37-
}
38-
}
39-
4028
/// Error type.
4129
#[derive(Debug, thiserror::Error)]
4230
pub enum Error {
@@ -48,7 +36,7 @@ pub enum Error {
4836
Transport(#[source] Box<dyn std::error::Error + Send + Sync>),
4937
/// JSON-RPC request error.
5038
#[error("JSON-RPC request error: {0:?}")]
51-
Request(#[source] JsonRpcErrorAlloc),
39+
Request(String),
5240
/// Frontend/backend channel error.
5341
#[error("Frontend/backend channel error: {0}")]
5442
Internal(#[source] futures_channel::mpsc::SendError),

types/src/v2/error.rs

Lines changed: 36 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -2,57 +2,30 @@ use crate::v2::params::{Id, TwoPointZero};
22
use serde::de::Deserializer;
33
use serde::ser::Serializer;
44
use serde::{Deserialize, Serialize};
5-
use serde_json::value::{RawValue, Value as JsonValue};
5+
use serde_json::value::RawValue;
66
use std::fmt;
77
use thiserror::Error;
88

99
/// [Failed JSON-RPC response object](https://www.jsonrpc.org/specification#response_object).
10-
#[derive(Serialize, Debug)]
10+
#[derive(Serialize, Deserialize, Debug, PartialEq)]
1111
pub struct JsonRpcError<'a> {
1212
/// JSON-RPC version.
1313
pub jsonrpc: TwoPointZero,
1414
/// Error.
15+
#[serde(borrow)]
1516
pub error: JsonRpcErrorObject<'a>,
1617
/// Request ID
17-
pub id: Option<&'a RawValue>,
18-
}
19-
/// [Failed JSON-RPC response object with allocations](https://www.jsonrpc.org/specification#response_object).
20-
#[derive(Error, Debug, Deserialize, PartialEq)]
21-
pub struct JsonRpcErrorAlloc {
22-
/// JSON-RPC version.
23-
pub jsonrpc: TwoPointZero,
24-
/// JSON-RPC error object.
25-
pub error: JsonRpcErrorObjectAlloc,
26-
/// Request ID.
27-
pub id: Id,
18+
pub id: Id<'a>,
2819
}
2920

30-
impl fmt::Display for JsonRpcErrorAlloc {
31-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
32-
write!(f, "{:?}: {:?}: {:?}", self.jsonrpc, self.error, self.id)
21+
impl<'a> fmt::Display for JsonRpcError<'a> {
22+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23+
write!(f, "{}", serde_json::to_string(&self).expect("infallible; qed"))
3324
}
3425
}
3526

3627
/// JSON-RPC error object.
37-
#[derive(Debug, PartialEq, Clone, Deserialize)]
38-
#[serde(deny_unknown_fields)]
39-
pub struct JsonRpcErrorObjectAlloc {
40-
/// Code
41-
pub code: JsonRpcErrorCode,
42-
/// Message
43-
pub message: String,
44-
/// Optional data
45-
pub data: Option<JsonValue>,
46-
}
47-
48-
impl From<JsonRpcErrorCode> for JsonRpcErrorObjectAlloc {
49-
fn from(code: JsonRpcErrorCode) -> Self {
50-
Self { code, message: code.message().to_owned(), data: None }
51-
}
52-
}
53-
54-
/// JSON-RPC error object with no extra allocations.
55-
#[derive(Debug, Serialize)]
28+
#[derive(Debug, Deserialize, Serialize, Clone)]
5629
#[serde(deny_unknown_fields)]
5730
pub struct JsonRpcErrorObject<'a> {
5831
/// Code
@@ -61,6 +34,7 @@ pub struct JsonRpcErrorObject<'a> {
6134
pub message: &'a str,
6235
/// Optional data
6336
#[serde(skip_serializing_if = "Option::is_none")]
37+
#[serde(borrow)]
6438
pub data: Option<&'a RawValue>,
6539
}
6640

@@ -70,6 +44,14 @@ impl<'a> From<JsonRpcErrorCode> for JsonRpcErrorObject<'a> {
7044
}
7145
}
7246

47+
impl<'a> PartialEq for JsonRpcErrorObject<'a> {
48+
fn eq(&self, other: &Self) -> bool {
49+
let this_raw = self.data.map(|r| r.get());
50+
let other_raw = self.data.map(|r| r.get());
51+
self.code == other.code && self.message == other.message && this_raw == other_raw
52+
}
53+
}
54+
7355
/// Parse error code.
7456
pub const PARSE_ERROR_CODE: i32 = -32700;
7557
/// Internal error code.
@@ -180,47 +162,44 @@ impl serde::Serialize for JsonRpcErrorCode {
180162

181163
#[cfg(test)]
182164
mod tests {
183-
use super::{
184-
Id, JsonRpcError, JsonRpcErrorAlloc, JsonRpcErrorCode, JsonRpcErrorObject, JsonRpcErrorObjectAlloc,
185-
TwoPointZero,
186-
};
165+
use super::{Id, JsonRpcError, JsonRpcErrorCode, JsonRpcErrorObject, TwoPointZero};
187166

188167
#[test]
189168
fn deserialize_works() {
190169
let ser = r#"{"jsonrpc":"2.0","error":{"code":-32700,"message":"Parse error"},"id":null}"#;
191-
let err: JsonRpcErrorAlloc = serde_json::from_str(ser).unwrap();
192-
assert_eq!(err.jsonrpc, TwoPointZero);
193-
assert_eq!(
194-
err.error,
195-
JsonRpcErrorObjectAlloc { code: JsonRpcErrorCode::ParseError, message: "Parse error".into(), data: None }
196-
);
197-
assert_eq!(err.id, Id::Null);
170+
let exp = JsonRpcError {
171+
jsonrpc: TwoPointZero,
172+
error: JsonRpcErrorObject { code: JsonRpcErrorCode::ParseError, message: "Parse error".into(), data: None },
173+
id: Id::Null,
174+
};
175+
let err: JsonRpcError = serde_json::from_str(ser).unwrap();
176+
assert_eq!(exp, err);
198177
}
199178

200179
#[test]
201180
fn deserialize_with_optional_data() {
202181
let ser = r#"{"jsonrpc":"2.0","error":{"code":-32700,"message":"Parse error", "data":"vegan"},"id":null}"#;
203-
let err: JsonRpcErrorAlloc = serde_json::from_str(ser).unwrap();
204-
assert_eq!(err.jsonrpc, TwoPointZero);
205-
assert_eq!(
206-
err.error,
207-
JsonRpcErrorObjectAlloc {
182+
let data = serde_json::value::to_raw_value(&"vegan").unwrap();
183+
let exp = JsonRpcError {
184+
jsonrpc: TwoPointZero,
185+
error: JsonRpcErrorObject {
208186
code: JsonRpcErrorCode::ParseError,
209187
message: "Parse error".into(),
210-
data: Some("vegan".into())
211-
}
212-
);
213-
assert_eq!(err.id, Id::Null);
188+
data: Some(&*data),
189+
},
190+
id: Id::Null,
191+
};
192+
let err: JsonRpcError = serde_json::from_str(ser).unwrap();
193+
assert_eq!(exp, err);
214194
}
215195

216196
#[test]
217197
fn serialize_works() {
218198
let exp = r#"{"jsonrpc":"2.0","error":{"code":-32603,"message":"Internal error"},"id":1337}"#;
219-
let raw_id = serde_json::value::to_raw_value(&1337).unwrap();
220199
let err = JsonRpcError {
221200
jsonrpc: TwoPointZero,
222201
error: JsonRpcErrorObject { code: JsonRpcErrorCode::InternalError, message: "Internal error", data: None },
223-
id: Some(&*raw_id),
202+
id: Id::Number(1337),
224203
};
225204
let ser = serde_json::to_string(&err).unwrap();
226205
assert_eq!(exp, ser);

0 commit comments

Comments
 (0)