1 //! HTTP extensions.
2 
3 use bytes::Bytes;
4 #[cfg(any(feature = "http1", feature = "ffi"))]
5 use http::header::HeaderName;
6 #[cfg(feature = "http1")]
7 use http::header::{IntoHeaderName, ValueIter};
8 use http::HeaderMap;
9 #[cfg(feature = "ffi")]
10 use std::collections::HashMap;
11 #[cfg(feature = "http2")]
12 use std::fmt;
13 
14 #[cfg(any(feature = "http1", feature = "ffi"))]
15 mod h1_reason_phrase;
16 #[cfg(any(feature = "http1", feature = "ffi"))]
17 pub use h1_reason_phrase::ReasonPhrase;
18 
19 #[cfg(feature = "http2")]
20 /// Represents the `:protocol` pseudo-header used by
21 /// the [Extended CONNECT Protocol].
22 ///
23 /// [Extended CONNECT Protocol]: https://datatracker.ietf.org/doc/html/rfc8441#section-4
24 #[derive(Clone, Eq, PartialEq)]
25 pub struct Protocol {
26     inner: h2::ext::Protocol,
27 }
28 
29 #[cfg(feature = "http2")]
30 impl Protocol {
31     /// Converts a static string to a protocol name.
from_static(value: &'static str) -> Self32     pub const fn from_static(value: &'static str) -> Self {
33         Self {
34             inner: h2::ext::Protocol::from_static(value),
35         }
36     }
37 
38     /// Returns a str representation of the header.
as_str(&self) -> &str39     pub fn as_str(&self) -> &str {
40         self.inner.as_str()
41     }
42 
43     #[cfg(feature = "server")]
from_inner(inner: h2::ext::Protocol) -> Self44     pub(crate) fn from_inner(inner: h2::ext::Protocol) -> Self {
45         Self { inner }
46     }
47 
into_inner(self) -> h2::ext::Protocol48     pub(crate) fn into_inner(self) -> h2::ext::Protocol {
49         self.inner
50     }
51 }
52 
53 #[cfg(feature = "http2")]
54 impl<'a> From<&'a str> for Protocol {
from(value: &'a str) -> Self55     fn from(value: &'a str) -> Self {
56         Self {
57             inner: h2::ext::Protocol::from(value),
58         }
59     }
60 }
61 
62 #[cfg(feature = "http2")]
63 impl AsRef<[u8]> for Protocol {
as_ref(&self) -> &[u8]64     fn as_ref(&self) -> &[u8] {
65         self.inner.as_ref()
66     }
67 }
68 
69 #[cfg(feature = "http2")]
70 impl fmt::Debug for Protocol {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result71     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
72         self.inner.fmt(f)
73     }
74 }
75 
76 /// A map from header names to their original casing as received in an HTTP message.
77 ///
78 /// If an HTTP/1 response `res` is parsed on a connection whose option
79 /// [`http1_preserve_header_case`] was set to true and the response included
80 /// the following headers:
81 ///
82 /// ```ignore
83 /// x-Bread: Baguette
84 /// X-BREAD: Pain
85 /// x-bread: Ficelle
86 /// ```
87 ///
88 /// Then `res.extensions().get::<HeaderCaseMap>()` will return a map with:
89 ///
90 /// ```ignore
91 /// HeaderCaseMap({
92 ///     "x-bread": ["x-Bread", "X-BREAD", "x-bread"],
93 /// })
94 /// ```
95 ///
96 /// [`http1_preserve_header_case`]: /client/struct.Client.html#method.http1_preserve_header_case
97 #[derive(Clone, Debug)]
98 pub(crate) struct HeaderCaseMap(HeaderMap<Bytes>);
99 
100 #[cfg(feature = "http1")]
101 impl HeaderCaseMap {
102     /// Returns a view of all spellings associated with that header name,
103     /// in the order they were found.
get_all<'a>( &'a self, name: &HeaderName, ) -> impl Iterator<Item = impl AsRef<[u8]> + 'a> + 'a104     pub(crate) fn get_all<'a>(
105         &'a self,
106         name: &HeaderName,
107     ) -> impl Iterator<Item = impl AsRef<[u8]> + 'a> + 'a {
108         self.get_all_internal(name).into_iter()
109     }
110 
111     /// Returns a view of all spellings associated with that header name,
112     /// in the order they were found.
get_all_internal<'a>(&'a self, name: &HeaderName) -> ValueIter<'_, Bytes>113     pub(crate) fn get_all_internal<'a>(&'a self, name: &HeaderName) -> ValueIter<'_, Bytes> {
114         self.0.get_all(name).into_iter()
115     }
116 
default() -> Self117     pub(crate) fn default() -> Self {
118         Self(Default::default())
119     }
120 
121     #[cfg(any(test, feature = "ffi"))]
insert(&mut self, name: HeaderName, orig: Bytes)122     pub(crate) fn insert(&mut self, name: HeaderName, orig: Bytes) {
123         self.0.insert(name, orig);
124     }
125 
append<N>(&mut self, name: N, orig: Bytes) where N: IntoHeaderName,126     pub(crate) fn append<N>(&mut self, name: N, orig: Bytes)
127     where
128         N: IntoHeaderName,
129     {
130         self.0.append(name, orig);
131     }
132 }
133 
134 #[cfg(feature = "ffi")]
135 #[derive(Clone, Debug)]
136 /// Hashmap<Headername, numheaders with that name>
137 pub(crate) struct OriginalHeaderOrder {
138     /// Stores how many entries a Headername maps to. This is used
139     /// for accounting.
140     num_entries: HashMap<HeaderName, usize>,
141     /// Stores the ordering of the headers. ex: `vec[i] = (headerName, idx)`,
142     /// The vector is ordered such that the ith element
143     /// represents the ith header that came in off the line.
144     /// The `HeaderName` and `idx` are then used elsewhere to index into
145     /// the multi map that stores the header values.
146     entry_order: Vec<(HeaderName, usize)>,
147 }
148 
149 #[cfg(all(feature = "http1", feature = "ffi"))]
150 impl OriginalHeaderOrder {
default() -> Self151     pub(crate) fn default() -> Self {
152         OriginalHeaderOrder {
153             num_entries: HashMap::new(),
154             entry_order: Vec::new(),
155         }
156     }
157 
insert(&mut self, name: HeaderName)158     pub(crate) fn insert(&mut self, name: HeaderName) {
159         if !self.num_entries.contains_key(&name) {
160             let idx = 0;
161             self.num_entries.insert(name.clone(), 1);
162             self.entry_order.push((name, idx));
163         }
164         // Replacing an already existing element does not
165         // change ordering, so we only care if its the first
166         // header name encountered
167     }
168 
append<N>(&mut self, name: N) where N: IntoHeaderName + Into<HeaderName> + Clone,169     pub(crate) fn append<N>(&mut self, name: N)
170     where
171         N: IntoHeaderName + Into<HeaderName> + Clone,
172     {
173         let name: HeaderName = name.into();
174         let idx;
175         if self.num_entries.contains_key(&name) {
176             idx = self.num_entries[&name];
177             *self.num_entries.get_mut(&name).unwrap() += 1;
178         } else {
179             idx = 0;
180             self.num_entries.insert(name.clone(), 1);
181         }
182         self.entry_order.push((name, idx));
183     }
184 
185     // No doc test is run here because `RUSTFLAGS='--cfg hyper_unstable_ffi'`
186     // is needed to compile. Once ffi is stablized `no_run` should be removed
187     // here.
188     /// This returns an iterator that provides header names and indexes
189     /// in the original order received.
190     ///
191     /// # Examples
192     /// ```no_run
193     /// use hyper::ext::OriginalHeaderOrder;
194     /// use hyper::header::{HeaderName, HeaderValue, HeaderMap};
195     ///
196     /// let mut h_order = OriginalHeaderOrder::default();
197     /// let mut h_map = Headermap::new();
198     ///
199     /// let name1 = b"Set-CookiE";
200     /// let value1 = b"a=b";
201     /// h_map.append(name1);
202     /// h_order.append(name1);
203     ///
204     /// let name2 = b"Content-Encoding";
205     /// let value2 = b"gzip";
206     /// h_map.append(name2, value2);
207     /// h_order.append(name2);
208     ///
209     /// let name3 = b"SET-COOKIE";
210     /// let value3 = b"c=d";
211     /// h_map.append(name3, value3);
212     /// h_order.append(name3)
213     ///
214     /// let mut iter = h_order.get_in_order()
215     ///
216     /// let (name, idx) = iter.next();
217     /// assert_eq!(b"a=b", h_map.get_all(name).nth(idx).unwrap());
218     ///
219     /// let (name, idx) = iter.next();
220     /// assert_eq!(b"gzip", h_map.get_all(name).nth(idx).unwrap());
221     ///
222     /// let (name, idx) = iter.next();
223     /// assert_eq!(b"c=d", h_map.get_all(name).nth(idx).unwrap());
224     /// ```
get_in_order(&self) -> impl Iterator<Item = &(HeaderName, usize)>225     pub(crate) fn get_in_order(&self) -> impl Iterator<Item = &(HeaderName, usize)> {
226         self.entry_order.iter()
227     }
228 }
229