use crate::response::{Code, FlowyResponse, ServerError}; use bytes::Bytes; use hyper::http; use protobuf::{Message, ProtobufError}; use reqwest::{Client, Response}; use std::{ convert::{TryFrom, TryInto}, time::Duration, }; use tokio::sync::oneshot; 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); }); let response = rx.await??; let data = get_response_data(response).await?; Ok(T2::try_from(data)?) } async fn get_response_data(original: Response) -> Result { if original.status() == http::StatusCode::OK { let bytes = original.bytes().await?; let response: FlowyResponse = serde_json::from_slice(&bytes)?; match response.error { None => Ok(response.data), Some(error) => Err(error), } } else { Err(ServerError::http(original)) } } 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() }, } }