use http::{StreamId, HttpResult, HttpError, Response, Header};
use http::transport::TransportStream;
use http::connection::{HttpConnection, SendStatus};
use http::session::{SessionState, DefaultSessionState, DefaultStream, Stream};
use http::client::{ClientConnection, HttpConnect, RequestStream};
pub struct SimpleClient<S> where S: TransportStream {
conn: ClientConnection<S, S>,
next_stream_id: u32,
host: Vec<u8>,
}
impl<S> SimpleClient<S> where S: TransportStream {
pub fn with_connection(conn: HttpConnection<S, S>, host: String)
-> HttpResult<SimpleClient<S>> {
let mut client = SimpleClient {
conn: ClientConnection::with_connection(conn, DefaultSessionState::new()),
next_stream_id: 1,
host: host.as_bytes().to_vec(),
};
try!(client.init());
Ok(client)
}
pub fn with_connector<C>(connector: C) -> HttpResult<SimpleClient<S>>
where C: HttpConnect<Stream=S> {
let stream = try!(connector.connect());
let conn = HttpConnection::<S, S>::with_stream(stream.0, stream.1);
SimpleClient::with_connection(conn, stream.2)
}
#[inline]
fn init(&mut self) -> HttpResult<()> {
self.conn.init()
}
pub fn request(&mut self, method: &[u8], path: &[u8], extras: &[Header], body: Option<Vec<u8>>)
-> HttpResult<StreamId> {
let stream = self.new_stream(method, path, extras, body);
let stream_id = stream.stream.id();
try!(self.conn.start_request(stream));
debug!("Trying to send the body");
while let SendStatus::Sent = try!(self.conn.send_next_data()) {
}
Ok(stream_id)
}
pub fn get_response(&mut self, stream_id: StreamId) -> HttpResult<Response> {
match self.conn.state.get_stream_ref(stream_id) {
None => return Err(HttpError::UnknownStreamId),
Some(_) => {},
};
loop {
if let Some(stream) = self.conn.state.get_stream_ref(stream_id) {
if stream.is_closed() {
return Ok(Response {
stream_id: stream.id(),
headers: stream.headers.clone().unwrap(),
body: stream.body.clone(),
});
}
}
try!(self.handle_next_frame());
}
}
pub fn get(&mut self, path: &[u8], extra_headers: &[Header])
-> HttpResult<Response> {
let stream_id = try!(self.request(b"GET", path, extra_headers, None));
self.get_response(stream_id)
}
pub fn post(&mut self, path: &[u8], extra_headers: &[Header], body: Vec<u8>)
-> HttpResult<Response> {
let stream_id = try!(self.request(b"POST", path, extra_headers, Some(body)));
self.get_response(stream_id)
}
fn new_stream(&mut self, method: &[u8], path: &[u8], extras: &[Header], body: Option<Vec<u8>>)
-> RequestStream<DefaultStream> {
let stream_id = self.get_next_stream_id();
let mut stream = DefaultStream::new(stream_id);
match body {
Some(body) => stream.set_full_data(body),
None => stream.close_local(),
};
let mut headers: Vec<Header> = vec![
(b":method".to_vec(), method.to_vec()),
(b":path".to_vec(), path.to_vec()),
(b":authority".to_vec(), self.host.clone()),
(b":scheme".to_vec(), self.conn.scheme().as_bytes().to_vec()),
];
headers.extend(extras.to_vec().into_iter());
RequestStream {
headers: headers,
stream: stream,
}
}
fn get_next_stream_id(&mut self) -> StreamId {
let ret = self.next_stream_id;
self.next_stream_id += 2;
ret
}
#[inline]
fn handle_next_frame(&mut self) -> HttpResult<()> {
self.conn.handle_next_frame()
}
}