1 use super::{DecoderError, NeedMore};
2 use crate::ext::Protocol;
3 
4 use bytes::Bytes;
5 use http::header::{HeaderName, HeaderValue};
6 use http::{Method, StatusCode};
7 use std::fmt;
8 
9 /// HTTP/2 Header
10 #[derive(Debug, Clone, Eq, PartialEq)]
11 pub enum Header<T = HeaderName> {
12     Field { name: T, value: HeaderValue },
13     // TODO: Change these types to `http::uri` types.
14     Authority(BytesStr),
15     Method(Method),
16     Scheme(BytesStr),
17     Path(BytesStr),
18     Protocol(Protocol),
19     Status(StatusCode),
20 }
21 
22 /// The header field name
23 #[derive(Debug, Clone, Eq, PartialEq, Hash)]
24 pub enum Name<'a> {
25     Field(&'a HeaderName),
26     Authority,
27     Method,
28     Scheme,
29     Path,
30     Protocol,
31     Status,
32 }
33 
34 #[doc(hidden)]
35 #[derive(Clone, Eq, PartialEq, Default)]
36 pub struct BytesStr(Bytes);
37 
len(name: &HeaderName, value: &HeaderValue) -> usize38 pub fn len(name: &HeaderName, value: &HeaderValue) -> usize {
39     let n: &str = name.as_ref();
40     32 + n.len() + value.len()
41 }
42 
43 impl Header<Option<HeaderName>> {
reify(self) -> Result<Header, HeaderValue>44     pub fn reify(self) -> Result<Header, HeaderValue> {
45         use self::Header::*;
46 
47         Ok(match self {
48             Field {
49                 name: Some(n),
50                 value,
51             } => Field { name: n, value },
52             Field { name: None, value } => return Err(value),
53             Authority(v) => Authority(v),
54             Method(v) => Method(v),
55             Scheme(v) => Scheme(v),
56             Path(v) => Path(v),
57             Protocol(v) => Protocol(v),
58             Status(v) => Status(v),
59         })
60     }
61 }
62 
63 impl Header {
new(name: Bytes, value: Bytes) -> Result<Header, DecoderError>64     pub fn new(name: Bytes, value: Bytes) -> Result<Header, DecoderError> {
65         if name.is_empty() {
66             return Err(DecoderError::NeedMore(NeedMore::UnexpectedEndOfStream));
67         }
68         if name[0] == b':' {
69             match &name[1..] {
70                 b"authority" => {
71                     let value = BytesStr::try_from(value)?;
72                     Ok(Header::Authority(value))
73                 }
74                 b"method" => {
75                     let method = Method::from_bytes(&value)?;
76                     Ok(Header::Method(method))
77                 }
78                 b"scheme" => {
79                     let value = BytesStr::try_from(value)?;
80                     Ok(Header::Scheme(value))
81                 }
82                 b"path" => {
83                     let value = BytesStr::try_from(value)?;
84                     Ok(Header::Path(value))
85                 }
86                 b"protocol" => {
87                     let value = Protocol::try_from(value)?;
88                     Ok(Header::Protocol(value))
89                 }
90                 b"status" => {
91                     let status = StatusCode::from_bytes(&value)?;
92                     Ok(Header::Status(status))
93                 }
94                 _ => Err(DecoderError::InvalidPseudoheader),
95             }
96         } else {
97             // HTTP/2 requires lower case header names
98             let name = HeaderName::from_lowercase(&name)?;
99             let value = HeaderValue::from_bytes(&value)?;
100 
101             Ok(Header::Field { name, value })
102         }
103     }
104 
len(&self) -> usize105     pub fn len(&self) -> usize {
106         match *self {
107             Header::Field {
108                 ref name,
109                 ref value,
110             } => len(name, value),
111             Header::Authority(ref v) => 32 + 10 + v.len(),
112             Header::Method(ref v) => 32 + 7 + v.as_ref().len(),
113             Header::Scheme(ref v) => 32 + 7 + v.len(),
114             Header::Path(ref v) => 32 + 5 + v.len(),
115             Header::Protocol(ref v) => 32 + 9 + v.as_str().len(),
116             Header::Status(_) => 32 + 7 + 3,
117         }
118     }
119 
120     /// Returns the header name
name(&self) -> Name121     pub fn name(&self) -> Name {
122         match *self {
123             Header::Field { ref name, .. } => Name::Field(name),
124             Header::Authority(..) => Name::Authority,
125             Header::Method(..) => Name::Method,
126             Header::Scheme(..) => Name::Scheme,
127             Header::Path(..) => Name::Path,
128             Header::Protocol(..) => Name::Protocol,
129             Header::Status(..) => Name::Status,
130         }
131     }
132 
value_slice(&self) -> &[u8]133     pub fn value_slice(&self) -> &[u8] {
134         match *self {
135             Header::Field { ref value, .. } => value.as_ref(),
136             Header::Authority(ref v) => v.as_ref(),
137             Header::Method(ref v) => v.as_ref().as_ref(),
138             Header::Scheme(ref v) => v.as_ref(),
139             Header::Path(ref v) => v.as_ref(),
140             Header::Protocol(ref v) => v.as_ref(),
141             Header::Status(ref v) => v.as_str().as_ref(),
142         }
143     }
144 
value_eq(&self, other: &Header) -> bool145     pub fn value_eq(&self, other: &Header) -> bool {
146         match *self {
147             Header::Field { ref value, .. } => {
148                 let a = value;
149                 match *other {
150                     Header::Field { ref value, .. } => a == value,
151                     _ => false,
152                 }
153             }
154             Header::Authority(ref a) => match *other {
155                 Header::Authority(ref b) => a == b,
156                 _ => false,
157             },
158             Header::Method(ref a) => match *other {
159                 Header::Method(ref b) => a == b,
160                 _ => false,
161             },
162             Header::Scheme(ref a) => match *other {
163                 Header::Scheme(ref b) => a == b,
164                 _ => false,
165             },
166             Header::Path(ref a) => match *other {
167                 Header::Path(ref b) => a == b,
168                 _ => false,
169             },
170             Header::Protocol(ref a) => match *other {
171                 Header::Protocol(ref b) => a == b,
172                 _ => false,
173             },
174             Header::Status(ref a) => match *other {
175                 Header::Status(ref b) => a == b,
176                 _ => false,
177             },
178         }
179     }
180 
is_sensitive(&self) -> bool181     pub fn is_sensitive(&self) -> bool {
182         match *self {
183             Header::Field { ref value, .. } => value.is_sensitive(),
184             // TODO: Technically these other header values can be sensitive too.
185             _ => false,
186         }
187     }
188 
skip_value_index(&self) -> bool189     pub fn skip_value_index(&self) -> bool {
190         use http::header;
191 
192         match *self {
193             Header::Field { ref name, .. } => matches!(
194                 *name,
195                 header::AGE
196                     | header::AUTHORIZATION
197                     | header::CONTENT_LENGTH
198                     | header::ETAG
199                     | header::IF_MODIFIED_SINCE
200                     | header::IF_NONE_MATCH
201                     | header::LOCATION
202                     | header::COOKIE
203                     | header::SET_COOKIE
204             ),
205             Header::Path(..) => true,
206             _ => false,
207         }
208     }
209 }
210 
211 // Mostly for tests
212 impl From<Header> for Header<Option<HeaderName>> {
from(src: Header) -> Self213     fn from(src: Header) -> Self {
214         match src {
215             Header::Field { name, value } => Header::Field {
216                 name: Some(name),
217                 value,
218             },
219             Header::Authority(v) => Header::Authority(v),
220             Header::Method(v) => Header::Method(v),
221             Header::Scheme(v) => Header::Scheme(v),
222             Header::Path(v) => Header::Path(v),
223             Header::Protocol(v) => Header::Protocol(v),
224             Header::Status(v) => Header::Status(v),
225         }
226     }
227 }
228 
229 impl<'a> Name<'a> {
into_entry(self, value: Bytes) -> Result<Header, DecoderError>230     pub fn into_entry(self, value: Bytes) -> Result<Header, DecoderError> {
231         match self {
232             Name::Field(name) => Ok(Header::Field {
233                 name: name.clone(),
234                 value: HeaderValue::from_bytes(&value)?,
235             }),
236             Name::Authority => Ok(Header::Authority(BytesStr::try_from(value)?)),
237             Name::Method => Ok(Header::Method(Method::from_bytes(&value)?)),
238             Name::Scheme => Ok(Header::Scheme(BytesStr::try_from(value)?)),
239             Name::Path => Ok(Header::Path(BytesStr::try_from(value)?)),
240             Name::Protocol => Ok(Header::Protocol(Protocol::try_from(value)?)),
241             Name::Status => {
242                 match StatusCode::from_bytes(&value) {
243                     Ok(status) => Ok(Header::Status(status)),
244                     // TODO: better error handling
245                     Err(_) => Err(DecoderError::InvalidStatusCode),
246                 }
247             }
248         }
249     }
250 
as_slice(&self) -> &[u8]251     pub fn as_slice(&self) -> &[u8] {
252         match *self {
253             Name::Field(ref name) => name.as_ref(),
254             Name::Authority => b":authority",
255             Name::Method => b":method",
256             Name::Scheme => b":scheme",
257             Name::Path => b":path",
258             Name::Protocol => b":protocol",
259             Name::Status => b":status",
260         }
261     }
262 }
263 
264 // ===== impl BytesStr =====
265 
266 impl BytesStr {
from_static(value: &'static str) -> Self267     pub(crate) const fn from_static(value: &'static str) -> Self {
268         BytesStr(Bytes::from_static(value.as_bytes()))
269     }
270 
from(value: &str) -> Self271     pub(crate) fn from(value: &str) -> Self {
272         BytesStr(Bytes::copy_from_slice(value.as_bytes()))
273     }
274 
275     #[doc(hidden)]
try_from(bytes: Bytes) -> Result<Self, std::str::Utf8Error>276     pub fn try_from(bytes: Bytes) -> Result<Self, std::str::Utf8Error> {
277         std::str::from_utf8(bytes.as_ref())?;
278         Ok(BytesStr(bytes))
279     }
280 
as_str(&self) -> &str281     pub(crate) fn as_str(&self) -> &str {
282         // Safety: check valid utf-8 in constructor
283         unsafe { std::str::from_utf8_unchecked(self.0.as_ref()) }
284     }
285 
into_inner(self) -> Bytes286     pub(crate) fn into_inner(self) -> Bytes {
287         self.0
288     }
289 }
290 
291 impl std::ops::Deref for BytesStr {
292     type Target = str;
deref(&self) -> &str293     fn deref(&self) -> &str {
294         self.as_str()
295     }
296 }
297 
298 impl AsRef<[u8]> for BytesStr {
as_ref(&self) -> &[u8]299     fn as_ref(&self) -> &[u8] {
300         self.0.as_ref()
301     }
302 }
303 
304 impl fmt::Debug for BytesStr {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result305     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
306         self.0.fmt(f)
307     }
308 }
309