hyper/proto/h1/
mod.rs

1#[cfg(all(feature = "server", feature = "runtime"))]
2use std::{pin::Pin, time::Duration};
3
4use bytes::BytesMut;
5use http::{HeaderMap, Method};
6use httparse::ParserConfig;
7#[cfg(all(feature = "server", feature = "runtime"))]
8use tokio::time::Sleep;
9
10use crate::body::DecodedLength;
11use crate::proto::{BodyLength, MessageHead};
12
13pub(crate) use self::conn::Conn;
14pub(crate) use self::decode::Decoder;
15pub(crate) use self::dispatch::Dispatcher;
16pub(crate) use self::encode::{EncodedBuf, Encoder};
17//TODO: move out of h1::io
18pub(crate) use self::io::MINIMUM_MAX_BUFFER_SIZE;
19
20mod conn;
21mod decode;
22pub(crate) mod dispatch;
23mod encode;
24mod io;
25mod role;
26
27cfg_client! {
28    pub(crate) type ClientTransaction = role::Client;
29}
30
31cfg_server! {
32    pub(crate) type ServerTransaction = role::Server;
33}
34
35pub(crate) trait Http1Transaction {
36    type Incoming;
37    type Outgoing: Default;
38    const LOG: &'static str;
39    fn parse(bytes: &mut BytesMut, ctx: ParseContext<'_>) -> ParseResult<Self::Incoming>;
40    fn encode(enc: Encode<'_, Self::Outgoing>, dst: &mut Vec<u8>) -> crate::Result<Encoder>;
41
42    fn on_error(err: &crate::Error) -> Option<MessageHead<Self::Outgoing>>;
43
44    fn is_client() -> bool {
45        !Self::is_server()
46    }
47
48    fn is_server() -> bool {
49        !Self::is_client()
50    }
51
52    fn should_error_on_parse_eof() -> bool {
53        Self::is_client()
54    }
55
56    fn should_read_first() -> bool {
57        Self::is_server()
58    }
59
60    fn update_date() {}
61}
62
63/// Result newtype for Http1Transaction::parse.
64pub(crate) type ParseResult<T> = Result<Option<ParsedMessage<T>>, crate::error::Parse>;
65
66#[derive(Debug)]
67pub(crate) struct ParsedMessage<T> {
68    head: MessageHead<T>,
69    decode: DecodedLength,
70    expect_continue: bool,
71    keep_alive: bool,
72    wants_upgrade: bool,
73}
74
75pub(crate) struct ParseContext<'a> {
76    cached_headers: &'a mut Option<HeaderMap>,
77    req_method: &'a mut Option<Method>,
78    h1_parser_config: ParserConfig,
79    #[cfg(all(feature = "server", feature = "runtime"))]
80    h1_header_read_timeout: Option<Duration>,
81    #[cfg(all(feature = "server", feature = "runtime"))]
82    h1_header_read_timeout_fut: &'a mut Option<Pin<Box<Sleep>>>,
83    #[cfg(all(feature = "server", feature = "runtime"))]
84    h1_header_read_timeout_running: &'a mut bool,
85    preserve_header_case: bool,
86    #[cfg(feature = "ffi")]
87    preserve_header_order: bool,
88    h09_responses: bool,
89    #[cfg(feature = "ffi")]
90    on_informational: &'a mut Option<crate::ffi::OnInformational>,
91    #[cfg(feature = "ffi")]
92    raw_headers: bool,
93}
94
95/// Passed to Http1Transaction::encode
96pub(crate) struct Encode<'a, T> {
97    head: &'a mut MessageHead<T>,
98    body: Option<BodyLength>,
99    #[cfg(feature = "server")]
100    keep_alive: bool,
101    req_method: &'a mut Option<Method>,
102    title_case_headers: bool,
103}
104
105/// Extra flags that a request "wants", like expect-continue or upgrades.
106#[derive(Clone, Copy, Debug)]
107struct Wants(u8);
108
109impl Wants {
110    const EMPTY: Wants = Wants(0b00);
111    const EXPECT: Wants = Wants(0b01);
112    const UPGRADE: Wants = Wants(0b10);
113
114    #[must_use]
115    fn add(self, other: Wants) -> Wants {
116        Wants(self.0 | other.0)
117    }
118
119    fn contains(&self, other: Wants) -> bool {
120        (self.0 & other.0) == other.0
121    }
122}