use std::convert::TryFrom; use std::error::Error; use std::fmt::Write; use std::str::FromStr; use std::{cmp, fmt, mem, str};
usecrate::header::name::HeaderName;
/// Represents an HTTP header field value. /// /// In practice, HTTP header field values are usually valid ASCII. However, the /// HTTP spec allows for a header value to contain opaque bytes as well. In this /// case, the header field value is not able to be represented as a string. /// /// To handle this, the `HeaderValue` is useable as a type and can be compared /// with strings and implements `Debug`. A `to_str` fn is provided that returns /// an `Err` if the header value contains non visible ascii characters. #[derive(Clone, Hash)] pubstruct HeaderValue {
inner: Bytes,
is_sensitive: bool,
}
/// A possible error when converting a `HeaderValue` from a string or byte /// slice. pubstruct InvalidHeaderValue {
_priv: (),
}
/// A possible error when converting a `HeaderValue` to a string representation. /// /// Header field values may contain opaque bytes, in which case it is not /// possible to represent the value as a string. #[derive(Debug)] pubstruct ToStrError {
_priv: (),
}
impl HeaderValue { /// Convert a static string to a `HeaderValue`. /// /// This function will not perform any copying, however the string is /// checked to ensure that no invalid characters are present. Only visible /// ASCII characters (32-127) are permitted. /// /// # Panics /// /// This function panics if the argument contains invalid header value /// characters. /// /// Until [Allow panicking in constants](https://github.com/rust-lang/rfcs/pull/2345) /// makes its way into stable, the panic message at compile-time is /// going to look cryptic, but should at least point at your header value: /// /// ```text /// error: any use of this value will cause an error /// --> http/src/header/value.rs:67:17 /// | /// 67 | ([] as [u8; 0])[0]; // Invalid header value /// | ^^^^^^^^^^^^^^^^^^ /// | | /// | index out of bounds: the length is 0 but the index is 0 /// | inside `HeaderValue::from_static` at http/src/header/value.rs:67:17 /// | inside `INVALID_HEADER` at src/main.rs:73:33 /// | /// ::: src/main.rs:73:1 /// | /// 73 | const INVALID_HEADER: HeaderValue = HeaderValue::from_static("жsome value"); /// | ---------------------------------------------------------------------------- /// ``` /// /// # Examples /// /// ``` /// # use http::header::HeaderValue; /// let val = HeaderValue::from_static("hello"); /// assert_eq!(val, "hello"); /// ``` #[inline] #[allow(unconditional_panic)] // required for the panic circumvention pubconstfn from_static(src: &'static str) -> HeaderValue { let bytes = src.as_bytes(); letmut i = 0; while i < bytes.len() { if !is_visible_ascii(bytes[i]) {
([] as [u8; 0])[0]; // Invalid header value
}
i += 1;
}
/// Attempt to convert a string to a `HeaderValue`. /// /// If the argument contains invalid header value characters, an error is /// returned. Only visible ASCII characters (32-127) are permitted. Use /// `from_bytes` to create a `HeaderValue` that includes opaque octets /// (128-255). /// /// This function is intended to be replaced in the future by a `TryFrom` /// implementation once the trait is stabilized in std. /// /// # Examples /// /// ``` /// # use http::header::HeaderValue; /// let val = HeaderValue::from_str("hello").unwrap(); /// assert_eq!(val, "hello"); /// ``` /// /// An invalid value /// /// ``` /// # use http::header::HeaderValue; /// let val = HeaderValue::from_str("\n"); /// assert!(val.is_err()); /// ``` #[inline] pubfn from_str(src: &str) -> Result<HeaderValue, InvalidHeaderValue> {
HeaderValue::try_from_generic(src, |s| Bytes::copy_from_slice(s.as_bytes()))
}
/// Converts a HeaderName into a HeaderValue /// /// Since every valid HeaderName is a valid HeaderValue this is done infallibly. /// /// # Examples /// /// ``` /// # use http::header::{HeaderValue, HeaderName}; /// # use http::header::ACCEPT; /// let val = HeaderValue::from_name(ACCEPT); /// assert_eq!(val, HeaderValue::from_bytes(b"accept").unwrap()); /// ``` #[inline] pubfn from_name(name: HeaderName) -> HeaderValue {
name.into()
}
/// Attempt to convert a byte slice to a `HeaderValue`. /// /// If the argument contains invalid header value bytes, an error is /// returned. Only byte values between 32 and 255 (inclusive) are permitted, /// excluding byte 127 (DEL). /// /// This function is intended to be replaced in the future by a `TryFrom` /// implementation once the trait is stabilized in std. /// /// # Examples /// /// ``` /// # use http::header::HeaderValue; /// let val = HeaderValue::from_bytes(b"hello\xfa").unwrap(); /// assert_eq!(val, &b"hello\xfa"[..]); /// ``` /// /// An invalid value /// /// ``` /// # use http::header::HeaderValue; /// let val = HeaderValue::from_bytes(b"\n"); /// assert!(val.is_err()); /// ``` #[inline] pubfn from_bytes(src: &[u8]) -> Result<HeaderValue, InvalidHeaderValue> {
HeaderValue::try_from_generic(src, Bytes::copy_from_slice)
}
/// Attempt to convert a `Bytes` buffer to a `HeaderValue`. /// /// This will try to prevent a copy if the type passed is the type used /// internally, and will copy the data if it is not. pubfn from_maybe_shared<T>(src: T) -> Result<HeaderValue, InvalidHeaderValue> where
T: AsRef<[u8]> + 'static,
{
if_downcast_into!(T, Bytes, src, { return HeaderValue::from_shared(src);
});
HeaderValue::from_bytes(src.as_ref())
}
/// Convert a `Bytes` directly into a `HeaderValue` without validating. /// /// This function does NOT validate that illegal bytes are not contained /// within the buffer. pubunsafefn from_maybe_shared_unchecked<T>(src: T) -> HeaderValue where
T: AsRef<[u8]> + 'static,
{ if cfg!(debug_assertions) { match HeaderValue::from_maybe_shared(src) {
Ok(val) => val,
Err(_err) => {
panic!("HeaderValue::from_maybe_shared_unchecked() with invalid bytes");
}
}
} else {
/// Yields a `&str` slice if the `HeaderValue` only contains visible ASCII /// chars. /// /// This function will perform a scan of the header value, checking all the /// characters. /// /// # Examples /// /// ``` /// # use http::header::HeaderValue; /// let val = HeaderValue::from_static("hello"); /// assert_eq!(val.to_str().unwrap(), "hello"); /// ``` pubfn to_str(&self) -> Result<&str, ToStrError> { let bytes = self.as_ref();
for &b in bytes { if !is_visible_ascii(b) { return Err(ToStrError { _priv: () });
}
}
unsafe { Ok(str::from_utf8_unchecked(bytes)) }
}
/// Returns the length of `self`. /// /// This length is in bytes. /// /// # Examples /// /// ``` /// # use http::header::HeaderValue; /// let val = HeaderValue::from_static("hello"); /// assert_eq!(val.len(), 5); /// ``` #[inline] pubfn len(&self) -> usize { self.as_ref().len()
}
/// Returns true if the `HeaderValue` has a length of zero bytes. /// /// # Examples /// /// ``` /// # use http::header::HeaderValue; /// let val = HeaderValue::from_static(""); /// assert!(val.is_empty()); /// /// let val = HeaderValue::from_static("hello"); /// assert!(!val.is_empty()); /// ``` #[inline] pubfn is_empty(&self) -> bool { self.len() == 0
}
/// Converts a `HeaderValue` to a byte slice. /// /// # Examples /// /// ``` /// # use http::header::HeaderValue; /// let val = HeaderValue::from_static("hello"); /// assert_eq!(val.as_bytes(), b"hello"); /// ``` #[inline] pubfn as_bytes(&self) -> &[u8] { self.as_ref()
}
/// Mark that the header value represents sensitive information. /// /// # Examples /// /// ``` /// # use http::header::HeaderValue; /// let mut val = HeaderValue::from_static("my secret"); /// /// val.set_sensitive(true); /// assert!(val.is_sensitive()); /// /// val.set_sensitive(false); /// assert!(!val.is_sensitive()); /// ``` #[inline] pubfn set_sensitive(&mutself, val: bool) { self.is_sensitive = val;
}
/// Returns `true` if the value represents sensitive data. /// /// Sensitive data could represent passwords or other data that should not /// be stored on disk or in memory. By marking header values as sensitive, /// components using this crate can be instructed to treat them with special /// care for security reasons. For example, caches can avoid storing /// sensitive values, and HPACK encoders used by HTTP/2.0 implementations /// can choose not to compress them. /// /// Additionally, sensitive values will be masked by the `Debug` /// implementation of `HeaderValue`. /// /// Note that sensitivity is not factored into equality or ordering. /// /// # Examples /// /// ``` /// # use http::header::HeaderValue; /// let mut val = HeaderValue::from_static("my secret"); /// /// val.set_sensitive(true); /// assert!(val.is_sensitive()); /// /// val.set_sensitive(false); /// assert!(!val.is_sensitive()); /// ``` #[inline] pubfn is_sensitive(&self) -> bool { self.is_sensitive
}
}
macro_rules! from_integers {
($($name:ident: $t:ident => $max_len:expr),*) => {$( impl From<$t> for HeaderValue { fn from(num: $t) -> HeaderValue { letmut buf = if mem::size_of::<BytesMut>() - 1 < $max_len { // On 32bit platforms, BytesMut max inline size // is 15 bytes, but the $max_len could be bigger. // // The likelihood of the number *actually* being // that big is very small, so only allocate // if the number needs that space. // // The largest decimal number in 15 digits: // It wold be 10.pow(15) - 1, but this is a constant // version. if num as u64 > 999_999_999_999_999_999 {
BytesMut::with_capacity($max_len)
} else { // fits inline...
BytesMut::new()
}
} else { // full value fits inline, so don't allocate!
BytesMut::new()
}; let _ = buf.write_str(::itoa::Buffer::new().format(num));
HeaderValue {
inner: buf.freeze(),
is_sensitive: false,
}
}
}
#[test] fn $name() { let n: $t = 55; let val = HeaderValue::from(n);
assert_eq!(val, &n.to_string());
let n = ::std::$t::MAX; let val = HeaderValue::from(n);
assert_eq!(val, &n.to_string());
}
)*};
}
from_integers! { // integer type => maximum decimal length
for &(value, expected) in cases { let val = HeaderValue::from_bytes(value.as_bytes()).unwrap(); let actual = format!("{:?}", val);
assert_eq!(expected, actual);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.