miasht 0.0.5

Minimum asynchronous HTTP server/client library
Documentation
use std::io::{self, BufRead, Read};
use httparse;
use futures::{Async, Future, Poll};

use {Error, Method, Status, Version};
use {Metadata, TransportStream};
use status::RawStatus;
use header::Headers;
use super::Connection;

#[derive(Debug)]
pub struct ReadRequest<T>(Option<Connection<T>>);
impl<T: TransportStream> ReadRequest<T> {
    pub fn new(mut connection: Connection<T>) -> Self {
        connection.inner.buffer.enter_read_phase();
        ReadRequest(Some(connection))
    }
}
impl<T: TransportStream> Future for ReadRequest<T> {
    type Item = Request<T>;
    type Error = Error;
    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        let mut connection = self.0.take().expect("Cannot poll ReadRequest twice");
        let (bytes, headers) = unsafe { connection.inner.buffer_and_headers() };
        let mut req = httparse::Request::new(headers);
        if let httparse::Status::Complete(body_offset) =
            track!(req.parse(bytes).map_err(Error::from))?
        {
            connection.inner.buffer.consume(body_offset);
            let version = if req.version.unwrap() == 0 {
                Version::Http1_0
            } else {
                debug_assert_eq!(req.version.unwrap(), 1);
                Version::Http1_1
            };
            let method = if let Some(method) = Method::try_from_str(req.method.unwrap()) {
                method
            } else {
                track_panic!(
                    Status::BadRequest,
                    "Unknown HTTP method: {}",
                    req.method.unwrap().to_string()
                );
            };
            Ok(Async::Ready(Request {
                version: version,
                path: req.path.unwrap(),
                method: method,
                headers: Headers::new(req.headers),
                connection: connection,
            }))
        } else {
            let filled = track!(connection.inner.fill_buffer().map_err(Error::from))?;
            self.0 = Some(connection);
            if filled {
                self.poll()
            } else {
                Ok(Async::NotReady)
            }
        }
    }
}

#[derive(Debug)]
pub struct Request<T> {
    version: Version,
    path: &'static str,
    method: Method,
    headers: Headers<'static>,
    connection: Connection<T>,
}
impl<T> Request<T> {
    pub fn version(&self) -> Version {
        self.version
    }
    pub fn path(&self) -> &str {
        self.path
    }
    pub fn method(&self) -> Method {
        self.method
    }
    pub fn headers(&self) -> &Headers {
        &self.headers
    }
    pub fn finish(mut self) -> Connection<T> {
        self.connection.version = self.version;
        self.connection
    }
}
impl<T: TransportStream> Read for Request<T> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        if !self.connection.inner.buffer.is_empty() {
            self.connection.inner.buffer.read(buf)
        } else {
            self.connection.inner.stream.read(buf)
        }
    }
}
impl<T> Metadata for Request<T> {
    fn version(&self) -> Version {
        self.version
    }
    fn method(&self) -> Option<Method> {
        Some(self.method)
    }
    fn path(&self) -> Option<&str> {
        Some(self.path)
    }
    fn status(&self) -> Option<&RawStatus> {
        None
    }
    fn headers(&self) -> &Headers {
        &self.headers
    }
}