1 //! Pieces pertaining to the HTTP message protocol. 2 use http::{HeaderMap, Method, StatusCode, Uri, Version}; 3 4 pub(crate) use self::h1::{dispatch, Conn, ServerTransaction}; 5 use self::body_length::DecodedLength; 6 7 pub(crate) mod h1; 8 pub(crate) mod h2; 9 10 /// An Incoming Message head. Includes request/status line, and headers. 11 #[derive(Clone, Debug, Default, PartialEq)] 12 pub struct MessageHead<S> { 13 /// HTTP version of the message. 14 pub version: Version, 15 /// Subject (request line or status line) of Incoming message. 16 pub subject: S, 17 /// Headers of the Incoming message. 18 pub headers: HeaderMap, 19 } 20 21 /// An incoming request message. 22 pub type RequestHead = MessageHead<RequestLine>; 23 24 #[derive(Debug, Default, PartialEq)] 25 pub struct RequestLine(pub Method, pub Uri); 26 27 /// An incoming response message. 28 pub type ResponseHead = MessageHead<StatusCode>; 29 30 #[derive(Debug)] 31 pub enum BodyLength { 32 /// Content-Length 33 Known(u64), 34 /// Transfer-Encoding: chunked (if h1) 35 Unknown, 36 } 37 38 /// Status of when a Disaptcher future completes. 39 pub(crate) enum Dispatched { 40 /// Dispatcher completely shutdown connection. 41 Shutdown, 42 /// Dispatcher has pending upgrade, and so did not shutdown. 43 Upgrade(::upgrade::Pending), 44 } 45 46 /// A separate module to encapsulate the invariants of the DecodedLength type. 47 mod body_length { 48 use std::fmt; 49 50 #[derive(Clone, Copy, Debug, PartialEq, Eq)] 51 pub(crate) struct DecodedLength(u64); 52 53 const MAX_LEN: u64 = ::std::u64::MAX - 2; 54 55 impl DecodedLength { 56 pub(crate) const CLOSE_DELIMITED: DecodedLength = DecodedLength(::std::u64::MAX); 57 pub(crate) const CHUNKED: DecodedLength = DecodedLength(::std::u64::MAX - 1); 58 pub(crate) const ZERO: DecodedLength = DecodedLength(0); 59 60 #[cfg(test)] new(len: u64) -> Self61 pub(crate) fn new(len: u64) -> Self { 62 debug_assert!(len <= MAX_LEN); 63 DecodedLength(len) 64 } 65 66 /// Takes the length as a content-length without other checks. 67 /// 68 /// Should only be called if previously confirmed this isn't 69 /// CLOSE_DELIMITED or CHUNKED. 70 #[inline] danger_len(self) -> u6471 pub(crate) fn danger_len(self) -> u64 { 72 debug_assert!(self.0 < Self::CHUNKED.0); 73 self.0 74 } 75 76 /// Converts to an Option<u64> representing a Known or Unknown length. into_opt(self) -> Option<u64>77 pub(crate) fn into_opt(self) -> Option<u64> { 78 match self { 79 DecodedLength::CHUNKED | 80 DecodedLength::CLOSE_DELIMITED => None, 81 DecodedLength(known) => Some(known) 82 } 83 } 84 85 /// Checks the `u64` is within the maximum allowed for content-length. checked_new(len: u64) -> Result<Self, ::error::Parse>86 pub(crate) fn checked_new(len: u64) -> Result<Self, ::error::Parse> { 87 if len <= MAX_LEN { 88 Ok(DecodedLength(len)) 89 } else { 90 warn!("content-length bigger than maximum: {} > {}", len, MAX_LEN); 91 Err(::error::Parse::TooLarge) 92 } 93 } 94 } 95 96 impl fmt::Display for DecodedLength { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result97 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 98 match *self { 99 DecodedLength::CLOSE_DELIMITED => f.write_str("close-delimited"), 100 DecodedLength::CHUNKED => f.write_str("chunked encoding"), 101 DecodedLength::ZERO => f.write_str("empty"), 102 DecodedLength(n) => write!(f, "content-length ({} bytes)", n), 103 } 104 } 105 } 106 } 107