1use 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
37pub 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(¶ms).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}