| 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 | MaxSizeReached, OccupiedEntry, VacantEntry, ValueDrain, ValueIter, ValueIterMut, Values, |
| 80 | ValuesMut, |
| 81 | }; |
| 82 | pub use self::name::{HeaderName, InvalidHeaderName}; |
| 83 | pub use self::value::{HeaderValue, InvalidHeaderValue, ToStrError}; |
| 84 | |
| 85 | // Use header name constants |
| 86 | #[rustfmt::skip] |
| 87 | pub use self::name::{ |
| 88 | ACCEPT, |
| 89 | ACCEPT_CHARSET, |
| 90 | ACCEPT_ENCODING, |
| 91 | ACCEPT_LANGUAGE, |
| 92 | ACCEPT_RANGES, |
| 93 | ACCESS_CONTROL_ALLOW_CREDENTIALS, |
| 94 | ACCESS_CONTROL_ALLOW_HEADERS, |
| 95 | ACCESS_CONTROL_ALLOW_METHODS, |
| 96 | ACCESS_CONTROL_ALLOW_ORIGIN, |
| 97 | ACCESS_CONTROL_EXPOSE_HEADERS, |
| 98 | ACCESS_CONTROL_MAX_AGE, |
| 99 | ACCESS_CONTROL_REQUEST_HEADERS, |
| 100 | ACCESS_CONTROL_REQUEST_METHOD, |
| 101 | AGE, |
| 102 | ALLOW, |
| 103 | ALT_SVC, |
| 104 | AUTHORIZATION, |
| 105 | CACHE_CONTROL, |
| 106 | CACHE_STATUS, |
| 107 | CDN_CACHE_CONTROL, |
| 108 | CONNECTION, |
| 109 | CONTENT_DISPOSITION, |
| 110 | CONTENT_ENCODING, |
| 111 | CONTENT_LANGUAGE, |
| 112 | CONTENT_LENGTH, |
| 113 | CONTENT_LOCATION, |
| 114 | CONTENT_RANGE, |
| 115 | CONTENT_SECURITY_POLICY, |
| 116 | CONTENT_SECURITY_POLICY_REPORT_ONLY, |
| 117 | CONTENT_TYPE, |
| 118 | COOKIE, |
| 119 | DNT, |
| 120 | DATE, |
| 121 | ETAG, |
| 122 | EXPECT, |
| 123 | EXPIRES, |
| 124 | FORWARDED, |
| 125 | FROM, |
| 126 | HOST, |
| 127 | IF_MATCH, |
| 128 | IF_MODIFIED_SINCE, |
| 129 | IF_NONE_MATCH, |
| 130 | IF_RANGE, |
| 131 | IF_UNMODIFIED_SINCE, |
| 132 | LAST_MODIFIED, |
| 133 | LINK, |
| 134 | LOCATION, |
| 135 | MAX_FORWARDS, |
| 136 | ORIGIN, |
| 137 | PRAGMA, |
| 138 | PROXY_AUTHENTICATE, |
| 139 | PROXY_AUTHORIZATION, |
| 140 | PUBLIC_KEY_PINS, |
| 141 | PUBLIC_KEY_PINS_REPORT_ONLY, |
| 142 | RANGE, |
| 143 | REFERER, |
| 144 | REFERRER_POLICY, |
| 145 | REFRESH, |
| 146 | RETRY_AFTER, |
| 147 | SEC_WEBSOCKET_ACCEPT, |
| 148 | SEC_WEBSOCKET_EXTENSIONS, |
| 149 | SEC_WEBSOCKET_KEY, |
| 150 | SEC_WEBSOCKET_PROTOCOL, |
| 151 | SEC_WEBSOCKET_VERSION, |
| 152 | SERVER, |
| 153 | SET_COOKIE, |
| 154 | STRICT_TRANSPORT_SECURITY, |
| 155 | TE, |
| 156 | TRAILER, |
| 157 | TRANSFER_ENCODING, |
| 158 | UPGRADE, |
| 159 | UPGRADE_INSECURE_REQUESTS, |
| 160 | USER_AGENT, |
| 161 | VARY, |
| 162 | VIA, |
| 163 | WARNING, |
| 164 | WWW_AUTHENTICATE, |
| 165 | X_CONTENT_TYPE_OPTIONS, |
| 166 | X_DNS_PREFETCH_CONTROL, |
| 167 | X_FRAME_OPTIONS, |
| 168 | X_XSS_PROTECTION, |
| 169 | }; |
| 170 | |
| 171 | /// Maximum length of a header name |
| 172 | /// |
| 173 | /// Generally, 64kb for a header name is WAY too much than would ever be needed |
| 174 | /// in practice. Restricting it to this size enables using `u16` values to |
| 175 | /// represent offsets when dealing with header names. |
| 176 | const MAX_HEADER_NAME_LEN: usize = (1 << 16) - 1; |
| 177 | |