1 | //! HTTP header types |
2 | //! |
3 | //! The module provides [`HeaderName`], [`HeaderMap`], and a number of types |
4 | //! used for interacting with `HeaderMap`. These types allow representing both |
5 | //! HTTP/1 and HTTP/2 headers. |
6 | //! |
7 | //! # `HeaderName` |
8 | //! |
9 | //! The `HeaderName` type represents both standard header names as well as |
10 | //! custom header names. The type handles the case insensitive nature of header |
11 | //! names and is used as the key portion of `HeaderMap`. Header names are |
12 | //! normalized to lower case. In other words, when creating a `HeaderName` with |
13 | //! a string, even if upper case characters are included, when getting a string |
14 | //! representation of the `HeaderName`, it will be all lower case. This allows |
15 | //! for faster `HeaderMap` comparison operations. |
16 | //! |
17 | //! The internal representation is optimized to efficiently handle the cases |
18 | //! most commonly encountered when working with HTTP. Standard header names are |
19 | //! special cased and are represented internally as an enum. Short custom |
20 | //! headers will be stored directly in the `HeaderName` struct and will not |
21 | //! incur any allocation overhead, however longer strings will require an |
22 | //! allocation for storage. |
23 | //! |
24 | //! ## Limitations |
25 | //! |
26 | //! `HeaderName` has a max length of 32,768 for header names. Attempting to |
27 | //! parse longer names will result in a panic. |
28 | //! |
29 | //! # `HeaderMap` |
30 | //! |
31 | //! `HeaderMap` is a map structure of header names highly optimized for use |
32 | //! cases common with HTTP. It is a [multimap] structure, where each header name |
33 | //! may have multiple associated header values. Given this, some of the APIs |
34 | //! diverge from [`HashMap`]. |
35 | //! |
36 | //! ## Overview |
37 | //! |
38 | //! Just like `HashMap` in Rust's stdlib, `HeaderMap` is based on [Robin Hood |
39 | //! hashing]. This algorithm tends to reduce the worst case search times in the |
40 | //! table and enables high load factors without seriously affecting performance. |
41 | //! Internally, keys and values are stored in vectors. As such, each insertion |
42 | //! will not incur allocation overhead. However, once the underlying vector |
43 | //! storage is full, a larger vector must be allocated and all values copied. |
44 | //! |
45 | //! ## Deterministic ordering |
46 | //! |
47 | //! Unlike Rust's `HashMap`, values in `HeaderMap` are deterministically |
48 | //! ordered. Roughly, values are ordered by insertion. This means that a |
49 | //! function that deterministically operates on a header map can rely on the |
50 | //! iteration order to remain consistent across processes and platforms. |
51 | //! |
52 | //! ## Adaptive hashing |
53 | //! |
54 | //! `HeaderMap` uses an adaptive hashing strategy in order to efficiently handle |
55 | //! most common cases. All standard headers have statically computed hash values |
56 | //! which removes the need to perform any hashing of these headers at runtime. |
57 | //! The default hash function emphasizes performance over robustness. However, |
58 | //! `HeaderMap` detects high collision rates and switches to a secure hash |
59 | //! function in those events. The threshold is set such that only denial of |
60 | //! service attacks should trigger it. |
61 | //! |
62 | //! ## Limitations |
63 | //! |
64 | //! `HeaderMap` can store a maximum of 32,768 headers (header name / value |
65 | //! pairs). Attempting to insert more will result in a panic. |
66 | //! |
67 | //! [`HeaderName`]: struct.HeaderName.html |
68 | //! [`HeaderMap`]: struct.HeaderMap.html |
69 | //! [multimap]: https://en.wikipedia.org/wiki/Multimap |
70 | //! [`HashMap`]: https://doc.rust-lang.org/std/collections/struct.HashMap.html |
71 | //! [Robin Hood hashing]: https://en.wikipedia.org/wiki/Hash_table#Robin_Hood_hashing |
72 | |
73 | mod map; |
74 | mod name; |
75 | mod value; |
76 | |
77 | pub use self::map::{ |
78 | AsHeaderName, Drain, Entry, GetAll, HeaderMap, IntoHeaderName, IntoIter, Iter, IterMut, Keys, |
79 | OccupiedEntry, VacantEntry, ValueDrain, ValueIter, ValueIterMut, Values, ValuesMut, |
80 | }; |
81 | pub use self::name::{HeaderName, InvalidHeaderName}; |
82 | pub use self::value::{HeaderValue, InvalidHeaderValue, ToStrError}; |
83 | |
84 | // Use header name constants |
85 | pub use self::name::{ |
86 | ACCEPT, |
87 | ACCEPT_CHARSET, |
88 | ACCEPT_ENCODING, |
89 | ACCEPT_LANGUAGE, |
90 | ACCEPT_RANGES, |
91 | ACCESS_CONTROL_ALLOW_CREDENTIALS, |
92 | ACCESS_CONTROL_ALLOW_HEADERS, |
93 | ACCESS_CONTROL_ALLOW_METHODS, |
94 | ACCESS_CONTROL_ALLOW_ORIGIN, |
95 | ACCESS_CONTROL_EXPOSE_HEADERS, |
96 | ACCESS_CONTROL_MAX_AGE, |
97 | ACCESS_CONTROL_REQUEST_HEADERS, |
98 | ACCESS_CONTROL_REQUEST_METHOD, |
99 | AGE, |
100 | ALLOW, |
101 | ALT_SVC, |
102 | AUTHORIZATION, |
103 | CACHE_CONTROL, |
104 | CACHE_STATUS, |
105 | CDN_CACHE_CONTROL, |
106 | CONNECTION, |
107 | CONTENT_DISPOSITION, |
108 | CONTENT_ENCODING, |
109 | CONTENT_LANGUAGE, |
110 | CONTENT_LENGTH, |
111 | CONTENT_LOCATION, |
112 | CONTENT_RANGE, |
113 | CONTENT_SECURITY_POLICY, |
114 | CONTENT_SECURITY_POLICY_REPORT_ONLY, |
115 | CONTENT_TYPE, |
116 | COOKIE, |
117 | DNT, |
118 | DATE, |
119 | ETAG, |
120 | EXPECT, |
121 | EXPIRES, |
122 | FORWARDED, |
123 | FROM, |
124 | HOST, |
125 | IF_MATCH, |
126 | IF_MODIFIED_SINCE, |
127 | IF_NONE_MATCH, |
128 | IF_RANGE, |
129 | IF_UNMODIFIED_SINCE, |
130 | LAST_MODIFIED, |
131 | LINK, |
132 | LOCATION, |
133 | MAX_FORWARDS, |
134 | ORIGIN, |
135 | PRAGMA, |
136 | PROXY_AUTHENTICATE, |
137 | PROXY_AUTHORIZATION, |
138 | PUBLIC_KEY_PINS, |
139 | PUBLIC_KEY_PINS_REPORT_ONLY, |
140 | RANGE, |
141 | REFERER, |
142 | REFERRER_POLICY, |
143 | REFRESH, |
144 | RETRY_AFTER, |
145 | SEC_WEBSOCKET_ACCEPT, |
146 | SEC_WEBSOCKET_EXTENSIONS, |
147 | SEC_WEBSOCKET_KEY, |
148 | SEC_WEBSOCKET_PROTOCOL, |
149 | SEC_WEBSOCKET_VERSION, |
150 | SERVER, |
151 | SET_COOKIE, |
152 | STRICT_TRANSPORT_SECURITY, |
153 | TE, |
154 | TRAILER, |
155 | TRANSFER_ENCODING, |
156 | UPGRADE, |
157 | UPGRADE_INSECURE_REQUESTS, |
158 | USER_AGENT, |
159 | VARY, |
160 | VIA, |
161 | WARNING, |
162 | WWW_AUTHENTICATE, |
163 | X_CONTENT_TYPE_OPTIONS, |
164 | X_DNS_PREFETCH_CONTROL, |
165 | X_FRAME_OPTIONS, |
166 | X_XSS_PROTECTION, |
167 | }; |
168 | |
169 | /// Maximum length of a header name |
170 | /// |
171 | /// Generally, 64kb for a header name is WAY too much than would ever be needed |
172 | /// in practice. Restricting it to this size enables using `u16` values to |
173 | /// represent offsets when dealing with header names. |
174 | const MAX_HEADER_NAME_LEN: usize = (1 << 16) - 1; |
175 | |