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