use reqwest::{Client, Error}; use serde::{Deserialize, Serialize}; use std::time::Duration; use trait_net::{client::ExecuteQuery, retry::policy::RetryOnError}; pub struct HttpBinClient { http_client: Client, } impl HttpBinClient { pub fn new() -> Self { Self { http_client: Client::new(), } } } #[derive(Clone, Debug, Serialize)] pub struct PostRequest { name: String, surname: String, } #[derive(Clone, Debug, Deserialize)] pub struct PostResponse { #[allow(dead_code)] data: String, } #[derive(Clone, Debug, Serialize)] pub struct UnavailableRequest; #[derive(Clone, Debug, Deserialize)] pub struct UnavailableResponse; impl ExecuteQuery for HttpBinClient { type Response = Result; async fn query(&self, request: PostRequest) -> Self::Response { println!("/post request"); let response = self .http_client .post("http://httpbin.org/post") .json(&request) .send() .await? .json() .await?; Ok(response) } async fn query_with_retry(&self, request: PostRequest) -> Self::Response { self.query_with_policy(request, RetryOnError::new(2, Duration::from_millis(100))) .await } } impl ExecuteQuery for HttpBinClient { type Response = Result; async fn query(&self, request: UnavailableRequest) -> Self::Response { println!("/status/503 request"); self.http_client .get("http://httpbin.org/status/503") .json(&request) .send() .await? .error_for_status()?; Ok(UnavailableResponse) } async fn query_with_retry(&self, request: UnavailableRequest) -> Self::Response { self.query_with_policy(request, RetryOnError::new(2, Duration::from_millis(100))) .await } } #[tokio::main] async fn main() { let client = HttpBinClient::new(); let request = PostRequest { name: "Foo".to_owned(), surname: "Bar".to_owned(), }; let response = client.query(request).await; println!("Response 1: {:?}", response); let request = UnavailableRequest; let response = client.query_with_retry(request).await; println!("Response 2: {:?}", response); }