blob: cb94e1058d72f810f9b8aaf703ee6a723623b17e [file] [log] [blame]
//! HTTP header types
//!
//! The module provides [`HeaderName`], [`HeaderMap`], and a number of types
//! used for interacting with [`HeaderMap`]. These types allow representing both
//! HTTP/1 and HTTP/2 headers.
//!
//! # `HeaderName`
//!
//! The `HeaderName` type represents both standard header names as well as
//! custom header names. The type handles the case insensitive nature of header
//! names and is used as the key portion of `HeaderMap`. Header names are
//! normalized to lower case. In other words, when creating a `HeaderName` with
//! a string, even if upper case characters are included, when getting a string
//! representation of the `HeaderName`, it will be all lower case. This allows
//! for faster `HeaderMap` comparison operations.
//!
//! The internal representation is optimized to efficiently handle the cases
//! most commonly encountered when working with HTTP. Standard header names are
//! special cased and are represented internally as an enum. Short custom
//! headers will be stored directly in the `HeaderName` struct and will not
//! incur any allocation overhead, however longer strings will require an
//! allocation for storage.
//!
//! ## Limitations
//!
//! `HeaderName` has a max length of 32,768 for header names. Attempting to
//! parse longer names will result in a panic.
//!
//! # `HeaderMap`
//!
//! `HeaderMap` is a map structure of header names highly optimized for use
//! cases common with HTTP. It is a [multimap] structure, where each header name
//! may have multiple associated header values. Given this, some of the APIs
//! diverge from [`HashMap`].
//!
//! ## Overview
//!
//! Just like `HashMap` in Rust's stdlib, `HeaderMap` is based on [Robin Hood
//! hashing]. This algorithm tends to reduce the worst case search times in the
//! table and enables high load factors without seriously affecting performance.
//! Internally, keys and values are stored in vectors. As such, each insertion
//! will not incur allocation overhead. However, once the underlying vector
//! storage is full, a larger vector must be allocated and all values copied.
//!
//! ## Deterministic ordering
//!
//! Unlike Rust's `HashMap`, values in `HeaderMap` are deterministically
//! ordered. Roughly, values are ordered by insertion. This means that a
//! function that deterministically operates on a header map can rely on the
//! iteration order to remain consistent across processes and platforms.
//!
//! ## Adaptive hashing
//!
//! `HeaderMap` uses an adaptive hashing strategy in order to efficiently handle
//! most common cases. All standard headers have statically computed hash values
//! which removes the need to perform any hashing of these headers at runtime.
//! The default hash function emphasizes performance over robustness. However,
//! `HeaderMap` detects high collision rates and switches to a secure hash
//! function in those events. The threshold is set such that only denial of
//! service attacks should trigger it.
//!
//! ## Limitations
//!
//! `HeaderMap` can store a maximum of 32,768 headers (header name / value
//! pairs). Attempting to insert more will result in a panic.
//!
//! [`HeaderName`]: #
//! [`HeaderMap`]: #
//! [multimap]: https://en.wikipedia.org/wiki/Multimap
//! [`HashMap`]: #
//! [Robin Hood hashing]: https://en.wikipedia.org/wiki/Hash_table#Robin_Hood_hashing
mod map;
mod name;
mod value;
pub use self::map::{
HeaderMap,
AsHeaderName,
IntoHeaderName,
Iter,
Keys,
Values,
Drain,
GetAll,
Entry,
VacantEntry,
OccupiedEntry,
ValueIter,
ValueIterMut,
ValueDrain,
IntoIter,
};
pub use self::name::{
HeaderName,
InvalidHeaderName,
InvalidHeaderNameBytes,
};
pub use self::value::{
HeaderValue,
InvalidHeaderValue,
InvalidHeaderValueBytes,
ToStrError,
};
// Use header name constants
pub use self::name::{
ACCEPT,
ACCEPT_CHARSET,
ACCEPT_ENCODING,
ACCEPT_LANGUAGE,
ACCEPT_RANGES,
ACCESS_CONTROL_ALLOW_CREDENTIALS,
ACCESS_CONTROL_ALLOW_HEADERS,
ACCESS_CONTROL_ALLOW_METHODS,
ACCESS_CONTROL_ALLOW_ORIGIN,
ACCESS_CONTROL_EXPOSE_HEADERS,
ACCESS_CONTROL_MAX_AGE,
ACCESS_CONTROL_REQUEST_HEADERS,
ACCESS_CONTROL_REQUEST_METHOD,
AGE,
ALLOW,
ALT_SVC,
AUTHORIZATION,
CACHE_CONTROL,
CONNECTION,
CONTENT_DISPOSITION,
CONTENT_ENCODING,
CONTENT_LANGUAGE,
CONTENT_LENGTH,
CONTENT_LOCATION,
CONTENT_RANGE,
CONTENT_SECURITY_POLICY,
CONTENT_SECURITY_POLICY_REPORT_ONLY,
CONTENT_TYPE,
COOKIE,
DNT,
DATE,
ETAG,
EXPECT,
EXPIRES,
FORWARDED,
FROM,
HOST,
IF_MATCH,
IF_MODIFIED_SINCE,
IF_NONE_MATCH,
IF_RANGE,
IF_UNMODIFIED_SINCE,
LAST_MODIFIED,
LINK,
LOCATION,
MAX_FORWARDS,
ORIGIN,
PRAGMA,
PROXY_AUTHENTICATE,
PROXY_AUTHORIZATION,
PUBLIC_KEY_PINS,
PUBLIC_KEY_PINS_REPORT_ONLY,
RANGE,
REFERER,
REFERRER_POLICY,
REFRESH,
RETRY_AFTER,
SERVER,
SET_COOKIE,
STRICT_TRANSPORT_SECURITY,
TE,
TRAILER,
TRANSFER_ENCODING,
UPGRADE,
UPGRADE_INSECURE_REQUESTS,
USER_AGENT,
VARY,
VIA,
WARNING,
WWW_AUTHENTICATE,
X_CONTENT_TYPE_OPTIONS,
X_DNS_PREFETCH_CONTROL,
X_FRAME_OPTIONS,
X_XSS_PROTECTION,
};
/// Maximum length of a header name
///
/// Generally, 64kb for a header name is WAY too much than would ever be needed
/// in practice. Restricting it to this size enables using `u16` values to
/// represent offsets when dealing with header names.
const MAX_HEADER_NAME_LEN: usize = 1 << 16;