use http::{Response, HttpResult, HttpError, HttpScheme, Header, StreamId};
use http::transport::TransportStream;
use http::connection::{HttpConnection, EndStream, SendStatus};
use http::session::{DefaultSessionState, SessionState, Stream};
use http::server::ServerConnection;
pub struct ServerRequest<'a> {
pub stream_id: StreamId,
pub headers: &'a [Header],
pub body: &'a [u8],
}
pub struct SimpleServer<TS, H> where TS: TransportStream, H: FnMut(ServerRequest) -> Response {
conn: ServerConnection<TS, TS>,
handler: H,
}
impl<TS, H> SimpleServer<TS, H>
where TS: TransportStream, H: FnMut(ServerRequest) -> Response {
pub fn new(mut stream: TS, handler: H) -> HttpResult<SimpleServer<TS, H>> {
let mut preface = [0; 24];
TransportStream::read_exact(&mut stream, &mut preface).unwrap();
if &preface != b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" {
return Err(HttpError::UnableToConnect);
}
let conn = HttpConnection::<TS, TS>::with_stream(stream, HttpScheme::Http);
let mut server = SimpleServer {
conn: ServerConnection::with_connection(conn, DefaultSessionState::new()),
handler: handler,
};
try!(server.conn.init());
Ok(server)
}
pub fn handle_next(&mut self) -> HttpResult<()> {
try!(self.conn.handle_next_frame());
let responses = try!(self.handle_requests());
try!(self.prepare_responses(responses));
try!(self.flush_streams());
try!(self.reap_streams());
Ok(())
}
fn handle_requests(&mut self) -> HttpResult<Vec<Response>> {
let handler = &mut self.handler;
Ok(self.conn.state.iter().filter(|s| s.is_closed_remote()).map(|stream| {
let req = ServerRequest {
stream_id: stream.stream_id,
headers: stream.headers.as_ref().unwrap(),
body: &stream.body,
};
handler(req)
}).collect())
}
fn prepare_responses(&mut self, responses: Vec<Response>) -> HttpResult<()> {
for response in responses.into_iter() {
try!(self.conn.start_response(
response.headers,
response.stream_id,
EndStream::No));
let mut stream = self.conn.state.get_stream_mut(response.stream_id).unwrap();
stream.set_full_data(response.body);
}
Ok(())
}
#[inline]
fn flush_streams(&mut self) -> HttpResult<()> {
while let SendStatus::Sent = try!(self.conn.send_next_data()) {}
Ok(())
}
#[inline]
fn reap_streams(&mut self) -> HttpResult<()> {
let _ = self.conn.state.get_closed();
Ok(())
}
}