use std::time::Duration;
use reqwest::{self, IntoUrl};
#[cfg(feature = "send3")]
use websocket::{
self, client::sync::Client as WsClient, result::WebSocketResult as WsResult,
stream::sync::NetworkStream as WsNetworkStream,
};
#[cfg(feature = "send3")]
const WEBSOCKET_PROTOCOL: &str = "ffsend";
pub struct Client {
config: ClientConfig,
reqwest: reqwest::Client,
}
impl Client {
pub fn new(config: ClientConfig, transfer: bool) -> Self {
let mut builder = reqwest::ClientBuilder::new();
match config.timeout {
Some(timeout) if !transfer => builder = builder.timeout(timeout),
_ => {}
}
match config.transfer_timeout {
Some(timeout) if transfer => builder = builder.timeout(timeout),
_ => {}
}
let reqwest = builder.build().expect("failed to build reqwest client");
Self { config, reqwest }
}
pub fn get<U: IntoUrl>(&self, url: U) -> reqwest::RequestBuilder {
self.configure(self.reqwest.get(url))
}
pub fn post<U: IntoUrl>(&self, url: U) -> reqwest::RequestBuilder {
self.configure(self.reqwest.post(url))
}
pub fn execute(&self, request: reqwest::Request) -> reqwest::Result<reqwest::Response> {
self.reqwest.execute(request)
}
#[cfg(feature = "send3")]
pub fn websocket(&self, url: &str) -> WsResult<WsClient<Box<dyn WsNetworkStream + Send>>> {
let mut builder = websocket::ClientBuilder::new(url)
.expect("failed to set up websocket builder")
.add_protocol(WEBSOCKET_PROTOCOL);
if let Some((user, password)) = &self.config.basic_auth {
let mut headers = websocket::header::Headers::new();
headers.set(websocket::header::Authorization(websocket::header::Basic {
username: user.to_owned(),
password: password.to_owned(),
}));
builder = builder.custom_headers(&headers);
}
builder.connect(None)
}
fn configure(&self, mut client: reqwest::RequestBuilder) -> reqwest::RequestBuilder {
if let Some((user, password)) = &self.config.basic_auth {
client = client.basic_auth(user, password.to_owned());
}
client
}
}
#[derive(Clone, Debug, Builder)]
pub struct ClientConfig {
timeout: Option<Duration>,
transfer_timeout: Option<Duration>,
basic_auth: Option<(String, Option<String>)>,
}
impl ClientConfig {
pub fn client(self, transfer: bool) -> Client {
Client::new(self, transfer)
}
}
impl Default for ClientConfig {
fn default() -> Self {
Self {
timeout: None,
transfer_timeout: None,
basic_auth: None,
}
}
}