1use http::Request;
2use http_by_chunks::{ConverterTo, HttpByChunks};
3use serde_json::Value;
4use std::{
5 io::{Read, Write},
6 net::{SocketAddr, TcpStream},
7};
8
9#[derive(Debug)]
10pub enum ClientError {
11 StatusCode(u16),
12 Io(std::io::Error),
13 Http(http::Error),
14 Serde(serde_json::Error),
15}
16
17impl From<std::io::Error> for ClientError {
18 fn from(value: std::io::Error) -> Self {
19 Self::Io(value)
20 }
21}
22
23impl From<http::Error> for ClientError {
24 fn from(value: http::Error) -> Self {
25 Self::Http(value)
26 }
27}
28
29impl From<serde_json::Error> for ClientError {
30 fn from(value: serde_json::Error) -> Self {
31 Self::Serde(value)
32 }
33}
34
35pub type Result<T> = std::result::Result<T, ClientError>;
36
37pub struct Client {
44 _addr: SocketAddr,
45 socket: TcpStream,
46 static_read_buf: [u8; 4096],
47 read_buf: Vec<u8>,
48}
49
50struct JsonConverter;
51impl ConverterTo<Value> for JsonConverter {
52 fn convert(&self, buf: &[u8]) -> Value {
53 serde_json::from_slice(buf).unwrap_or(Value::Null)
54 }
55}
56
57static JSON_CONVERTER: JsonConverter = JsonConverter;
58
59impl Client {
60 pub fn connect(addr: SocketAddr) -> Result<Self> {
67 let socket = TcpStream::connect(addr)?;
68 Ok(Self {
69 _addr: addr,
70 socket,
71 static_read_buf: [0; 4096],
72 read_buf: Vec::new(),
73 })
74 }
75
76 pub fn get(&mut self, uri: &str) -> Result<Value> {
82 self.do_no_body("GET", uri)
83 }
84
85 pub fn gets<const X: usize>(&mut self, uris: &[&str; X]) -> Result<[Option<Result<Value>>; X]> {
102 self.do_no_bodys("GET", uris)
103 }
104
105 pub fn delete(&mut self, uri: &str) -> Result<Value> {
111 self.do_no_body("DELETE", uri)
112 }
113
114 pub fn deletes<const X: usize>(
120 &mut self,
121 uris: &[&str; X],
122 ) -> Result<[Option<Result<Value>>; X]> {
123 self.do_no_bodys("DELETE", uris)
124 }
125
126 pub fn post(&mut self, uri: &str, value: Value) -> Result<Value> {
132 self.do_body("POST", uri, value)
133 }
134
135 pub fn posts<const X: usize>(
141 &mut self,
142 uris: &[&str; X],
143 values: &[Value; X],
144 ) -> Result<[Option<Result<Value>>; X]> {
145 self.do_bodys("POST", uris, values)
146 }
147
148 pub fn put(&mut self, uri: &str, value: Value) -> Result<Value> {
154 self.do_body("PUT", uri, value)
155 }
156
157 pub fn puts<const X: usize>(
163 &mut self,
164 uris: &[&str; X],
165 values: &[Value; X],
166 ) -> Result<[Option<Result<Value>>; X]> {
167 self.do_bodys("PUT", uris, values)
168 }
169
170 pub fn patch(&mut self, uri: &str, value: Value) -> Result<Value> {
176 self.do_body("PATCH", uri, value)
177 }
178
179 pub fn patches<const X: usize>(
185 &mut self,
186 uris: &[&str; X],
187 values: &[Value; X],
188 ) -> Result<[Option<Result<Value>>; X]> {
189 self.do_bodys("PATCH", uris, values)
190 }
191
192 fn do_no_body(&mut self, method: &str, uri: &str) -> Result<Value> {
193 let req = Request::builder()
194 .method(method)
195 .uri(uri)
196 .body(Value::Null)?;
197 self.send_request(&req)?;
198 self.read_response()
199 }
200
201 fn do_no_bodys<const X: usize>(
202 &mut self,
203 method: &str,
204 uris: &[&str; X],
205 ) -> Result<[Option<Result<Value>>; X]> {
206 let mut res = [const { None }; X];
207 for uri in uris {
208 let req = Request::builder()
209 .method(method)
210 .uri(*uri)
211 .body(Value::Null)?;
212 self.send_request(&req)?;
213 }
214 (0..uris.len()).for_each(|x| {
215 res[x] = Some(self.read_response());
216 });
217 Ok(res)
218 }
219
220 fn do_body(&mut self, method: &str, uri: &str, value: Value) -> Result<Value> {
221 let req = Request::builder().method(method).uri(uri).body(value)?;
222 self.send_request(&req)?;
223 self.read_response()
224 }
225
226 fn do_bodys<const X: usize>(
227 &mut self,
228 method: &str,
229 uris: &[&str; X],
230 values: &[Value; X],
231 ) -> Result<[Option<Result<Value>>; X]> {
232 let mut res = [const { None }; X];
233 for i in 0..uris.len() {
234 let req = Request::builder()
235 .method(method)
236 .uri(uris[i])
237 .body(values[i].clone())?;
238 self.send_request(&req)?;
239 }
240 (0..uris.len()).for_each(|x| {
241 res[x] = Some(self.read_response());
242 });
243 Ok(res)
244 }
245
246 fn send_request(&mut self, req: &Request<Value>) -> Result<()> {
247 self.socket.write_all(&req_to_bytes(req))?;
248 Ok(())
249 }
250
251 fn read_response(&mut self) -> Result<Value> {
252 let mut c = HttpByChunks::<Value>::new(&JSON_CONVERTER);
253 loop {
254 let n = self.socket.read(&mut self.static_read_buf)?;
255 self.read_buf.extend_from_slice(&self.static_read_buf[..n]);
256 self.read_buf = c.append(&self.read_buf).to_vec();
257 if let Some(resp) = c.build_response() {
258 let mut resp = resp?;
259 if !resp.status().is_success() {
260 return Err(ClientError::StatusCode(resp.status().as_u16()));
261 }
262 return Ok(resp.body_mut().take());
263 }
264 }
265 }
266}
267
268fn req_to_bytes(req: &Request<Value>) -> Vec<u8> {
269 let mut res = vec![];
270 res.extend_from_slice(format!("{} {} HTTP/1.1\r\n", req.method(), req.uri()).as_bytes());
271 if *req.body() == Value::Null {
272 res.extend_from_slice("\r\n".to_string().as_bytes());
273 } else if let Ok(b) = serde_json::to_vec(req.body()) {
274 res.extend_from_slice(format!("Content-Length: {}\r\n\r\n", b.len()).as_bytes());
275 res.extend_from_slice(&b);
276 }
277 res
278}