//! Pieces pertaining to the HTTP message protocol. use std::borrow::Cow; use std::fmt; use bytes::BytesMut; use header::{Connection, ConnectionOption, Expect}; use header::Headers; use method::Method; use status::StatusCode; use uri::Uri; use version::HttpVersion; use version::HttpVersion::{Http10, Http11}; pub use self::conn::{Conn, KeepAlive, KA}; pub use self::body::{Body, TokioBody}; pub use self::chunk::Chunk; mod body; mod chunk; mod conn; mod io; mod h1; //mod h2; pub mod request; pub mod response; /// An Incoming Message head. Includes request/status line, and headers. #[derive(Clone, Debug, Default, PartialEq)] pub struct MessageHead { /// HTTP version of the message. pub version: HttpVersion, /// Subject (request line or status line) of Incoming message. pub subject: S, /// Headers of the Incoming message. pub headers: Headers } /// An incoming request message. pub type RequestHead = MessageHead; #[derive(Debug, Default, PartialEq)] pub struct RequestLine(pub Method, pub Uri); impl fmt::Display for RequestLine { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{} {}", self.0, self.1) } } /// An incoming response message. pub type ResponseHead = MessageHead; impl MessageHead { pub fn should_keep_alive(&self) -> bool { should_keep_alive(self.version, &self.headers) } pub fn expecting_continue(&self) -> bool { expecting_continue(self.version, &self.headers) } } impl ResponseHead { /// Converts this head's RawStatus into a StatusCode. #[inline] pub fn status(&self) -> StatusCode { self.subject.status() } } /// The raw status code and reason-phrase. #[derive(Clone, PartialEq, Debug)] pub struct RawStatus(pub u16, pub Cow<'static, str>); impl RawStatus { /// Converts this into a StatusCode. #[inline] pub fn status(&self) -> StatusCode { StatusCode::try_from(self.0).unwrap() } } impl fmt::Display for RawStatus { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{} {}", self.0, self.1) } } impl From for RawStatus { fn from(status: StatusCode) -> RawStatus { RawStatus(status.into(), Cow::Borrowed(status.canonical_reason().unwrap_or(""))) } } impl Default for RawStatus { fn default() -> RawStatus { RawStatus(200, Cow::Borrowed("OK")) } } impl From> for MessageHead { fn from(head: MessageHead<::StatusCode>) -> MessageHead { MessageHead { subject: head.subject.into(), version: head.version, headers: head.headers, } } } /// Checks if a connection should be kept alive. #[inline] pub fn should_keep_alive(version: HttpVersion, headers: &Headers) -> bool { let ret = match (version, headers.get::()) { (Http10, None) => false, (Http10, Some(conn)) if !conn.contains(&ConnectionOption::KeepAlive) => false, (Http11, Some(conn)) if conn.contains(&ConnectionOption::Close) => false, _ => true }; trace!("should_keep_alive(version={:?}, header={:?}) = {:?}", version, headers.get::(), ret); ret } /// Checks if a connection is expecting a `100 Continue` before sending its body. #[inline] pub fn expecting_continue(version: HttpVersion, headers: &Headers) -> bool { let ret = match (version, headers.get::()) { (Http11, Some(&Expect::Continue)) => true, _ => false }; trace!("expecting_continue(version={:?}, header={:?}) = {:?}", version, headers.get::(), ret); ret } #[derive(Debug)] pub enum ServerTransaction {} #[derive(Debug)] pub enum ClientTransaction {} pub trait Http1Transaction { type Incoming; type Outgoing: Default; fn parse(bytes: &mut BytesMut) -> ParseResult; fn decoder(head: &MessageHead, method: &mut Option<::Method>) -> ::Result; fn encode(head: MessageHead, has_body: bool, method: &mut Option, dst: &mut Vec) -> h1::Encoder; } pub type ParseResult = ::Result, usize)>>; #[test] fn test_should_keep_alive() { let mut headers = Headers::new(); assert!(!should_keep_alive(Http10, &headers)); assert!(should_keep_alive(Http11, &headers)); headers.set(Connection::close()); assert!(!should_keep_alive(Http10, &headers)); assert!(!should_keep_alive(Http11, &headers)); headers.set(Connection::keep_alive()); assert!(should_keep_alive(Http10, &headers)); assert!(should_keep_alive(Http11, &headers)); } #[test] fn test_expecting_continue() { let mut headers = Headers::new(); assert!(!expecting_continue(Http10, &headers)); assert!(!expecting_continue(Http11, &headers)); headers.set(Expect::Continue); assert!(!expecting_continue(Http10, &headers)); assert!(expecting_continue(Http11, &headers)); }