Skip to main content

jsonrpsee_test_utils/
helpers.rs

1// Copyright 2019-2021 Parity Technologies (UK) Ltd.
2//
3// Permission is hereby granted, free of charge, to any
4// person obtaining a copy of this software and associated
5// documentation files (the "Software"), to deal in the
6// Software without restriction, including without
7// limitation the rights to use, copy, modify, merge,
8// publish, distribute, sublicense, and/or sell copies of
9// the Software, and to permit persons to whom the Software
10// is furnished to do so, subject to the following
11// conditions:
12//
13// The above copyright notice and this permission notice
14// shall be included in all copies or substantial portions
15// of the Software.
16//
17// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
18// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
19// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
20// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
21// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
24// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25// DEALINGS IN THE SOFTWARE.
26
27use std::net::SocketAddr;
28
29use crate::mocks::{HttpResponse, Id, Uri};
30use http_body_util::BodyExt;
31use hyper_util::{client::legacy::Client, rt::TokioExecutor};
32use serde::Serialize;
33use serde_json::Value;
34
35pub type Body = http_body_util::Full<hyper::body::Bytes>;
36
37/// Converts a sockaddress to a HTTP URI.
38pub fn to_http_uri(sockaddr: SocketAddr) -> Uri {
39    let s = sockaddr.to_string();
40    Uri::builder().scheme("http").authority(s.as_str()).path_and_query("/").build().unwrap()
41}
42
43pub fn ok_response(result: Value, id: Id) -> String {
44    format!(
45        r#"{{"jsonrpc":"2.0","id":{},"result":{}}}"#,
46        serde_json::to_string(&id).unwrap(),
47        result
48    )
49}
50
51pub fn method_not_found(id: Id) -> String {
52    format!(
53        r#"{{"jsonrpc":"2.0","id":{},"error":{{"code":-32601,"message":"Method not found"}}}}"#,
54        serde_json::to_string(&id).unwrap()
55    )
56}
57
58pub fn parse_error(id: Id) -> String {
59    format!(
60        r#"{{"jsonrpc":"2.0","id":{},"error":{{"code":-32700,"message":"Parse error"}}}}"#,
61        serde_json::to_string(&id).unwrap()
62    )
63}
64
65pub fn oversized_request(max_limit: u32) -> String {
66    format!(
67        r#"{{"jsonrpc":"2.0","id":null,"error":{{"code":-32007,"message":"Request is too big","data":"Exceeded max limit of {max_limit}"}}}}"#
68    )
69}
70
71pub fn batches_not_supported() -> String {
72    r#"{"jsonrpc":"2.0","id":null,"error":{"code":-32005,"message":"Batched requests are not supported by this server"}}"#.into()
73}
74
75pub fn batches_too_large(max_limit: usize) -> String {
76    format!(
77        r#"{{"jsonrpc":"2.0","id":null,"error":{{"code":-32010,"message":"The batch request was too large","data":"Exceeded max limit of {max_limit}"}}}}"#
78    )
79}
80
81pub fn batch_response_too_large(max_limit: usize) -> String {
82    format!(
83        r#"{{"jsonrpc":"2.0","id":null,"error":{{"code":-32011,"message":"The batch response was too large","data":"Exceeded max limit of {max_limit}"}}}}"#
84    )
85}
86
87pub fn oversized_response(id: Id, max_limit: u32) -> String {
88    format!(
89        r#"{{"jsonrpc":"2.0","id":{},"error":{{"code":-32008,"message":"Response is too big","data":"Exceeded max limit of {}"}}}}"#,
90        serde_json::to_string(&id).unwrap(),
91        max_limit,
92    )
93}
94
95pub fn invalid_request(id: Id) -> String {
96    format!(
97        r#"{{"jsonrpc":"2.0","id":{},"error":{{"code":-32600,"message":"Invalid request"}}}}"#,
98        serde_json::to_string(&id).unwrap()
99    )
100}
101
102pub fn invalid_batch(ids: Vec<Id>) -> String {
103    use std::fmt::Write;
104    let mut result = String::new();
105    result.push('[');
106    for (i, id) in ids.iter().enumerate() {
107        write!(
108            result,
109            r#"{{"jsonrpc":"2.0","id":{},"error":{{"code":-32600,"message":"Invalid request"}}}}{}"#,
110            serde_json::to_string(&id).unwrap(),
111            if i + 1 == ids.len() { "" } else { "," }
112        )
113        .unwrap();
114    }
115    result.push(']');
116    result
117}
118
119pub fn invalid_params(id: Id) -> String {
120    format!(
121        r#"{{"jsonrpc":"2.0","id":{},"error":{{"code":-32602,"message":"Invalid params"}}}}"#,
122        serde_json::to_string(&id).unwrap()
123    )
124}
125
126pub fn call<T: Serialize>(method: &str, params: Vec<T>, id: Id) -> String {
127    format!(
128        r#"{{"jsonrpc":"2.0","method":{},"params":{},"id":{}}}"#,
129        serde_json::to_string(method).unwrap(),
130        serde_json::to_string(&params).unwrap(),
131        serde_json::to_string(&id).unwrap()
132    )
133}
134
135pub fn call_execution_failed(msg: &str, id: Id) -> String {
136    format!(
137        r#"{{"jsonrpc":"2.0","id":{},"error":{{"code":-32000,"message":"{}"}}}}"#,
138        serde_json::to_string(&id).unwrap(),
139        msg,
140    )
141}
142
143pub fn internal_error(id: Id) -> String {
144    format!(
145        r#"{{"jsonrpc":"2.0","id":{},"error":{{"code":-32603,"message":"Internal error"}}}}"#,
146        serde_json::to_string(&id).unwrap()
147    )
148}
149
150pub async fn http_request(body: Body, uri: Uri) -> Result<HttpResponse, String> {
151    let client = hyper_util::client::legacy::Client::builder(TokioExecutor::new()).build_http();
152    http_post(client, body, uri).await
153}
154
155pub async fn http2_request(body: Body, uri: Uri) -> Result<HttpResponse, String> {
156    let client = hyper_util::client::legacy::Client::builder(TokioExecutor::new()).build_http();
157    http_post(client, body, uri).await
158}
159
160async fn http_post<C>(client: Client<C, Body>, body: Body, uri: Uri) -> Result<HttpResponse, String>
161where
162    C: hyper_util::client::legacy::connect::Connect + Clone + Send + Sync + 'static,
163{
164    let r = hyper::Request::post(uri)
165        .header(
166            hyper::header::CONTENT_TYPE,
167            hyper::header::HeaderValue::from_static("application/json"),
168        )
169        .body(body)
170        .expect("uri and request headers are valid; qed");
171    let res = client.request(r).await.map_err(|e| format!("{e:?}"))?;
172
173    let (parts, mut body) = res.into_parts();
174    let mut bytes = Vec::new();
175
176    while let Some(frame) = body.frame().await {
177        let data = frame.unwrap().into_data().unwrap();
178        bytes.extend(data);
179    }
180
181    Ok(HttpResponse {
182        status: parts.status,
183        header: parts.headers,
184        body: String::from_utf8(bytes.to_vec()).unwrap(),
185    })
186}