use crate::{errors::NetworkError, future::ResultFuture}; use bytes::Bytes; use protobuf::{Message, ProtobufError}; use reqwest::{Client, Error, Response}; use std::{ convert::{TryFrom, TryInto}, time::Duration, }; use tokio::sync::{oneshot, oneshot::error::RecvError}; // pub async fn http_post(url: &str, data: T1) -> ResultFuture where // T1: TryInto + Send + Sync + 'static, // T2: TryFrom + Send + Sync + 'static, // { // let url = url.to_owned(); // ResultFuture::new(async move { post(url, data).await }) // } pub async fn http_post(url: &str, data: T1) -> Result where T1: TryInto, T2: TryFrom, { let request_bytes: Bytes = data.try_into()?; let url = url.to_owned(); let (tx, rx) = oneshot::channel::>(); tokio::spawn(async move { let client = default_client(); let response = client.post(&url).body(request_bytes).send().await; tx.send(response); }); match rx.await { Ok(response) => { let response = response?; let response_bytes = response.bytes().await?; let data = T2::try_from(response_bytes)?; Ok(data) }, Err(e) => { unimplemented!() }, } } async fn parse_response(response: Response) -> Result where T: Message, { let bytes = response.bytes().await?; parse_bytes(bytes) } fn parse_bytes(bytes: Bytes) -> Result where T: Message, { match Message::parse_from_bytes(&bytes) { Ok(data) => Ok(data), Err(e) => { log::error!( "Parse bytes for {:?} failed: {}", std::any::type_name::(), e ); Err(e.into()) }, } } fn default_client() -> Client { let result = reqwest::Client::builder() .connect_timeout(Duration::from_millis(500)) .timeout(Duration::from_secs(5)) .build(); match result { Ok(client) => client, Err(e) => { log::error!("Create reqwest client failed: {}", e); reqwest::Client::new() }, } }