use std::io;
use std::io::Read;
use std::sync::{Arc, Mutex, Weak};
use transport::Transport;
use super::*;
pub struct Client {
max_connections: Option<u16>,
options: Options,
transport_pool: Arc<Mutex<Vec<Transport>>>,
transport_count: u16,
}
impl Default for Client {
fn default() -> Client {
Client::new()
}
}
impl Client {
pub fn builder() -> ClientBuilder {
ClientBuilder::default()
}
pub fn new() -> Self {
Self::builder().build()
}
pub fn get(&self, uri: &str) -> Result<Response, Error> {
let request = http::Request::get(uri).body(Body::Empty)?;
self.send(request)
}
pub fn post<B: Into<Body>>(&self, uri: &str, body: B) -> Result<Response, Error> {
let request = http::Request::post(uri).body(body.into())?;
self.send(request)
}
pub fn put<B: Into<Body>>(&self, uri: &str, body: B) -> Result<Response, Error> {
let request = http::Request::put(uri).body(body.into())?;
self.send(request)
}
pub fn delete(&self, uri: &str) -> Result<Response, Error> {
let request = http::Request::delete(uri).body(Body::Empty)?;
self.send(request)
}
pub fn send(&self, request: Request) -> Result<Response, Error> {
if let Some(mut transport) = self.get_transport() {
let mut response = transport.execute(request)?;
let stream = self.create_stream(transport);
response
.body(Body::from_reader(stream))
.map_err(Into::into)
} else {
Err(Error::TooManyConnections)
}
}
fn get_transport(&self) -> Option<Transport> {
let mut pool = self.transport_pool.lock().unwrap();
if let Some(transport) = pool.pop() {
return Some(transport);
}
if let Some(max) = self.max_connections {
if self.transport_count >= max {
return None;
}
}
Some(self.create_transport())
}
fn create_transport(&self) -> Transport {
Transport::with_options(self.options.clone())
}
fn create_stream(&self, transport: Transport) -> Stream {
Stream {
pool: Arc::downgrade(&self.transport_pool),
transport: Some(transport),
}
}
}
#[derive(Clone)]
pub struct ClientBuilder {
max_connections: Option<u16>,
options: Options,
}
impl Default for ClientBuilder {
fn default() -> ClientBuilder {
ClientBuilder {
max_connections: Some(8),
options: Default::default(),
}
}
}
impl ClientBuilder {
pub fn max_connections(mut self, max: Option<u16>) -> Self {
self.max_connections = max;
self
}
pub fn options(mut self, options: Options) -> Self {
self.options = options;
self
}
pub fn build(self) -> Client {
Client {
max_connections: self.max_connections,
options: self.options,
transport_pool: Arc::new(Mutex::new(Vec::new())),
transport_count: 0,
}
}
}
struct Stream {
pool: Weak<Mutex<Vec<Transport>>>,
transport: Option<Transport>,
}
impl Read for Stream {
fn read(&mut self, buffer: &mut [u8]) -> io::Result<usize> {
self.transport.as_mut().unwrap().read(buffer)
}
}
impl Drop for Stream {
fn drop(&mut self) {
if let Some(transport) = self.transport.take() {
if let Some(pool) = self.pool.upgrade() {
pool.lock()
.unwrap()
.push(transport);
}
}
}
}