use bytes::Bytes; use hyper::Body; use serde::{de::DeserializeOwned, Serialize}; use super::net::TurmoilConnector; /// An hyper client that resolves URI within a turmoil simulation. pub struct Client(hyper::Client<TurmoilConnector>); pub struct Response(hyper::Response<Body>); impl Response { pub async fn json<T: DeserializeOwned>(self) -> anyhow::Result<T> { let bytes = hyper::body::to_bytes(self.0.into_body()).await?; let v = serde_json::from_slice(&bytes)?; Ok(v) } pub async fn json_value(self) -> anyhow::Result<serde_json::Value> { self.json().await } pub async fn body_string(self) -> anyhow::Result<String> { let bytes = hyper::body::to_bytes(self.0.into_body()).await?; Ok(String::from_utf8(bytes.to_vec())?) } pub fn status(&self) -> hyper::http::StatusCode { self.0.status() } } impl Client { pub fn new() -> Self { let connector = TurmoilConnector; Self(hyper::client::Client::builder().build(connector)) } pub async fn get(&self, s: &str) -> anyhow::Result<Response> { Ok(Response(self.0.get(s.parse()?).await?)) } pub(crate) async fn post<T: Serialize>(&self, url: &str, body: T) -> anyhow::Result<Response> { let bytes: Bytes = serde_json::to_vec(&body)?.into(); let body = Body::from(bytes); let request = hyper::Request::post(url) .header("Content-Type", "application/json") .body(body)?; let resp = self.0.request(request).await?; Ok(Response(resp)) } pub(crate) async fn delete<T: Serialize>( &self, url: &str, body: T, ) -> anyhow::Result<Response> { let bytes: Bytes = serde_json::to_vec(&body)?.into(); let body = Body::from(bytes); let request = hyper::Request::delete(url) .header("Content-Type", "application/json") .body(body)?; let resp = self.0.request(request).await?; Ok(Response(resp)) } }