//! HTTP cookie parsing and cookie jar management. //! //! This crates provides the [`Cookie`] type, representing an HTTP cookie, and //! the [`CookieJar`] type, which manages a collection of cookies for session //! management, recording changes as they are made, and optional automatic //! cookie encryption and signing. //! //! # Usage //! //! Add the following to the `[dependencies]` section of your `Cargo.toml`: //! //! ```toml //! cookie = "0.16" //! ``` //! //! # Features //! //! This crate exposes several features, all of which are disabled by default: //! //! * **`percent-encode`** //! //! Enables _percent encoding and decoding_ of names and values in cookies. //! //! When this feature is enabled, the [`Cookie::encoded()`] and //! [`Cookie::parse_encoded()`] methods are available. The `encoded` method //! returns a wrapper around a `Cookie` whose `Display` implementation //! percent-encodes the name and value of the cookie. The `parse_encoded` //! method percent-decodes the name and value of a `Cookie` during parsing. //! //! * **`signed`** //! //! Enables _signed_ cookies via [`CookieJar::signed()`]. //! //! When this feature is enabled, the [`CookieJar::signed()`] method, //! [`SignedJar`] type, and [`Key`] type are available. The jar acts as "child //! jar"; operations on the jar automatically sign and verify cookies as they //! are added and retrieved from the parent jar. //! //! * **`private`** //! //! Enables _private_ (authenticated, encrypted) cookies via //! [`CookieJar::private()`]. //! //! When this feature is enabled, the [`CookieJar::private()`] method, //! [`PrivateJar`] type, and [`Key`] type are available. The jar acts as "child //! jar"; operations on the jar automatically encrypt and decrypt/authenticate //! cookies as they are added and retrieved from the parent jar. //! //! * **`key-expansion`** //! //! Enables _key expansion_ or _key derivation_ via [`Key::derive_from()`]. //! //! When this feature is enabled, and either `signed` or `private` are _also_ //! enabled, the [`Key::derive_from()`] method is available. The method can be //! used to derive a `Key` structure appropriate for use with signed and //! private jars from cryptographically valid key material that is shorter in //! length than the full key. //! //! * **`secure`** //! //! A meta-feature that simultaneously enables `signed`, `private`, and //! `key-expansion`. //! //! You can enable features via `Cargo.toml`: //! //! ```toml //! [dependencies.cookie] //! features = ["secure", "percent-encode"] //! ```
#[derive(Debug, Clone)] enum CookieStr<'c> { /// An string derived from indexes (start, end).
Indexed(usize, usize), /// A string derived from a concrete string.
Concrete(Cow<'c, str>),
}
impl<'c> CookieStr<'c> { /// Retrieves the string `self` corresponds to. If `self` is derived from /// indexes, the corresponding subslice of `string` is returned. Otherwise, /// the concrete string is returned. /// /// # Panics /// /// Panics if `self` is an indexed string and `string` is None. fn to_str<'s>(&'s self, string: Option<&'s Cow<str>>) -> &'s str { match *self {
CookieStr::Indexed(i, j) => { let s = string.expect("`Some` base string must exist when \
converting indexed str to str! (This is a module invariant.)");
&s[i..j]
},
CookieStr::Concrete(ref cstr) => &*cstr,
}
}
/// Representation of an HTTP cookie. /// /// # Constructing a `Cookie` /// /// To construct a cookie with only a name/value, use [`Cookie::new()`]: /// /// ```rust /// use cookie::Cookie; /// /// let cookie = Cookie::new("name", "value"); /// assert_eq!(&cookie.to_string(), "name=value"); /// ``` /// /// To construct more elaborate cookies, use [`Cookie::build()`] and /// [`CookieBuilder`] methods: /// /// ```rust /// use cookie::Cookie; /// /// let cookie = Cookie::build("name", "value") /// .domain("www.rust-lang.org") /// .path("/") /// .secure(true) /// .http_only(true) /// .finish(); /// ``` #[derive(Debug, Clone)] pubstruct Cookie<'c> { /// Storage for the cookie string. Only used if this structure was derived /// from a string that was subsequently parsed.
cookie_string: Option<Cow<'c, str>>, /// The cookie's name.
name: CookieStr<'c>, /// The cookie's value.
value: CookieStr<'c>, /// The cookie's expiration, if any.
expires: Option<Expiration>, /// The cookie's maximum age, if any.
max_age: Option<Duration>, /// The cookie's domain, if any.
domain: Option<CookieStr<'c>>, /// The cookie's path domain, if any.
path: Option<CookieStr<'c>>, /// Whether this cookie was marked Secure.
secure: Option<bool>, /// Whether this cookie was marked HttpOnly.
http_only: Option<bool>, /// The draft `SameSite` attribute.
same_site: Option<SameSite>,
}
impl<'c> Cookie<'c> { /// Creates a new `Cookie` with the given name and value. /// /// # Example /// /// ```rust /// use cookie::Cookie; /// /// let cookie = Cookie::new("name", "value"); /// assert_eq!(cookie.name_value(), ("name", "value")); /// ``` pubfn new<N, V>(name: N, value: V) -> Self where N: Into<Cow<'c, str>>,
V: Into<Cow<'c, str>>
{
Cookie {
cookie_string: None,
name: CookieStr::Concrete(name.into()),
value: CookieStr::Concrete(value.into()),
expires: None,
max_age: None,
domain: None,
path: None,
secure: None,
http_only: None,
same_site: None,
}
}
/// Creates a new `Cookie` with the given name and an empty value. /// /// # Example /// /// ```rust /// use cookie::Cookie; /// /// let cookie = Cookie::named("name"); /// assert_eq!(cookie.name(), "name"); /// assert!(cookie.value().is_empty()); /// ``` pubfn named<N>(name: N) -> Cookie<'c> where N: Into<Cow<'c, str>>
{
Cookie::new(name, "")
}
/// Creates a new `CookieBuilder` instance from the given key and value /// strings. /// /// # Example /// /// ``` /// use cookie::Cookie; /// /// let c = Cookie::build("foo", "bar").finish(); /// assert_eq!(c.name_value(), ("foo", "bar")); /// ``` pubfn build<N, V>(name: N, value: V) -> CookieBuilder<'c> where N: Into<Cow<'c, str>>,
V: Into<Cow<'c, str>>
{
CookieBuilder::new(name, value)
}
/// Parses a `Cookie` from the given HTTP cookie header value string. Does /// not perform any percent-decoding. /// /// # Example /// /// ``` /// use cookie::Cookie; /// /// let c = Cookie::parse("foo=bar%20baz; HttpOnly").unwrap(); /// assert_eq!(c.name_value(), ("foo", "bar%20baz")); /// assert_eq!(c.http_only(), Some(true)); /// ``` pubfn parse<S>(s: S) -> Result<Cookie<'c>, ParseError> where S: Into<Cow<'c, str>>
{
parse_cookie(s, false)
}
/// Parses a `Cookie` from the given HTTP cookie header value string where /// the name and value fields are percent-encoded. Percent-decodes the /// name/value fields. /// /// # Example /// /// ``` /// use cookie::Cookie; /// /// let c = Cookie::parse_encoded("foo=bar%20baz; HttpOnly").unwrap(); /// assert_eq!(c.name_value(), ("foo", "bar baz")); /// assert_eq!(c.http_only(), Some(true)); /// ``` #[cfg(feature = "percent-encode")] #[cfg_attr(all(nightly, doc), doc(cfg(feature = "percent-encode")))] pubfn parse_encoded<S>(s: S) -> Result<Cookie<'c>, ParseError> where S: Into<Cow<'c, str>>
{
parse_cookie(s, true)
}
/// Converts `self` into a `Cookie` with a static lifetime with as few /// allocations as possible. /// /// # Example /// /// ``` /// use cookie::Cookie; /// /// let c = Cookie::new("a", "b"); /// let owned_cookie = c.into_owned(); /// assert_eq!(owned_cookie.name_value(), ("a", "b")); /// ``` pubfn into_owned(self) -> Cookie<'static> {
Cookie {
cookie_string: self.cookie_string.map(|s| s.into_owned().into()),
name: self.name.into_owned(),
value: self.value.into_owned(),
expires: self.expires,
max_age: self.max_age,
domain: self.domain.map(|s| s.into_owned()),
path: self.path.map(|s| s.into_owned()),
secure: self.secure,
http_only: self.http_only,
same_site: self.same_site,
}
}
/// Returns the name of `self`. /// /// # Example /// /// ``` /// use cookie::Cookie; /// /// let c = Cookie::new("name", "value"); /// assert_eq!(c.name(), "name"); /// ``` #[inline] pubfn name(&self) -> &str { self.name.to_str(self.cookie_string.as_ref())
}
/// Returns the value of `self`. /// /// # Example /// /// ``` /// use cookie::Cookie; /// /// let c = Cookie::new("name", "value"); /// assert_eq!(c.value(), "value"); /// ``` #[inline] pubfn value(&self) -> &str { self.value.to_str(self.cookie_string.as_ref())
}
/// Returns the name and value of `self` as a tuple of `(name, value)`. /// /// # Example /// /// ``` /// use cookie::Cookie; /// /// let c = Cookie::new("name", "value"); /// assert_eq!(c.name_value(), ("name", "value")); /// ``` #[inline] pubfn name_value(&self) -> (&str, &str) {
(self.name(), self.value())
}
/// Returns whether this cookie was marked `HttpOnly` or not. Returns /// `Some(true)` when the cookie was explicitly set (manually or parsed) as /// `HttpOnly`, `Some(false)` when `http_only` was manually set to `false`, /// and `None` otherwise. /// /// # Example /// /// ``` /// use cookie::Cookie; /// /// let c = Cookie::parse("name=value; httponly").unwrap(); /// assert_eq!(c.http_only(), Some(true)); /// /// let mut c = Cookie::new("name", "value"); /// assert_eq!(c.http_only(), None); /// /// let mut c = Cookie::new("name", "value"); /// assert_eq!(c.http_only(), None); /// /// // An explicitly set "false" value. /// c.set_http_only(false); /// assert_eq!(c.http_only(), Some(false)); /// /// // An explicitly set "true" value. /// c.set_http_only(true); /// assert_eq!(c.http_only(), Some(true)); /// ``` #[inline] pubfn http_only(&self) -> Option<bool> { self.http_only
}
/// Returns whether this cookie was marked `Secure` or not. Returns /// `Some(true)` when the cookie was explicitly set (manually or parsed) as /// `Secure`, `Some(false)` when `secure` was manually set to `false`, and /// `None` otherwise. /// /// # Example /// /// ``` /// use cookie::Cookie; /// /// let c = Cookie::parse("name=value; Secure").unwrap(); /// assert_eq!(c.secure(), Some(true)); /// /// let mut c = Cookie::parse("name=value").unwrap(); /// assert_eq!(c.secure(), None); /// /// let mut c = Cookie::new("name", "value"); /// assert_eq!(c.secure(), None); /// /// // An explicitly set "false" value. /// c.set_secure(false); /// assert_eq!(c.secure(), Some(false)); /// /// // An explicitly set "true" value. /// c.set_secure(true); /// assert_eq!(c.secure(), Some(true)); /// ``` #[inline] pubfn secure(&self) -> Option<bool> { self.secure
}
/// Returns the `SameSite` attribute of this cookie if one was specified. /// /// # Example /// /// ``` /// use cookie::{Cookie, SameSite}; /// /// let c = Cookie::parse("name=value; SameSite=Lax").unwrap(); /// assert_eq!(c.same_site(), Some(SameSite::Lax)); /// ``` #[inline] pubfn same_site(&self) -> Option<SameSite> { self.same_site
}
/// Returns the specified max-age of the cookie if one was specified. /// /// # Example /// /// ``` /// use cookie::Cookie; /// /// let c = Cookie::parse("name=value").unwrap(); /// assert_eq!(c.max_age(), None); /// /// let c = Cookie::parse("name=value; Max-Age=3600").unwrap(); /// assert_eq!(c.max_age().map(|age| age.whole_hours()), Some(1)); /// ``` #[inline] pubfn max_age(&self) -> Option<Duration> { self.max_age
}
/// Returns the `Path` of the cookie if one was specified. /// /// # Example /// /// ``` /// use cookie::Cookie; /// /// let c = Cookie::parse("name=value").unwrap(); /// assert_eq!(c.path(), None); /// /// let c = Cookie::parse("name=value; Path=/").unwrap(); /// assert_eq!(c.path(), Some("/")); /// /// let c = Cookie::parse("name=value; path=/sub").unwrap(); /// assert_eq!(c.path(), Some("/sub")); /// ``` #[inline] pubfn path(&self) -> Option<&str> { matchself.path {
Some(ref c) => Some(c.to_str(self.cookie_string.as_ref())),
None => None,
}
}
/// Returns the `Domain` of the cookie if one was specified. /// /// # Example /// /// ``` /// use cookie::Cookie; /// /// let c = Cookie::parse("name=value").unwrap(); /// assert_eq!(c.domain(), None); /// /// let c = Cookie::parse("name=value; Domain=crates.io").unwrap(); /// assert_eq!(c.domain(), Some("crates.io")); /// ``` #[inline] pubfn domain(&self) -> Option<&str> { matchself.domain {
Some(ref c) => Some(c.to_str(self.cookie_string.as_ref())),
None => None,
}
}
/// Returns the [`Expiration`] of the cookie if one was specified. /// /// # Example /// /// ``` /// use cookie::{Cookie, Expiration}; /// /// let c = Cookie::parse("name=value").unwrap(); /// assert_eq!(c.expires(), None); /// /// // Here, `cookie.expires_datetime()` returns `None`. /// let c = Cookie::build("name", "value").expires(None).finish(); /// assert_eq!(c.expires(), Some(Expiration::Session)); /// /// let expire_time = "Wed, 21 Oct 2017 07:28:00 GMT"; /// let cookie_str = format!("name=value; Expires={}", expire_time); /// let c = Cookie::parse(cookie_str).unwrap(); /// assert_eq!(c.expires().and_then(|e| e.datetime()).map(|t| t.year()), Some(2017)); /// ``` #[inline] pubfn expires(&self) -> Option<Expiration> { self.expires
}
/// Returns the expiration date-time of the cookie if one was specified. /// /// # Example /// /// ``` /// use cookie::Cookie; /// /// let c = Cookie::parse("name=value").unwrap(); /// assert_eq!(c.expires_datetime(), None); /// /// // Here, `cookie.expires()` returns `Some`. /// let c = Cookie::build("name", "value").expires(None).finish(); /// assert_eq!(c.expires_datetime(), None); /// /// let expire_time = "Wed, 21 Oct 2017 07:28:00 GMT"; /// let cookie_str = format!("name=value; Expires={}", expire_time); /// let c = Cookie::parse(cookie_str).unwrap(); /// assert_eq!(c.expires_datetime().map(|t| t.year()), Some(2017)); /// ``` #[inline] pubfn expires_datetime(&self) -> Option<OffsetDateTime> { self.expires.and_then(|e| e.datetime())
}
/// Sets the name of `self` to `name`. /// /// # Example /// /// ``` /// use cookie::Cookie; /// /// let mut c = Cookie::new("name", "value"); /// assert_eq!(c.name(), "name"); /// /// c.set_name("foo"); /// assert_eq!(c.name(), "foo"); /// ``` pubfn set_name<N: Into<Cow<'c, str>>>(&mut self, name: N) { self.name = CookieStr::Concrete(name.into())
}
/// Sets the value of `self` to `value`. /// /// # Example /// /// ``` /// use cookie::Cookie; /// /// let mut c = Cookie::new("name", "value"); /// assert_eq!(c.value(), "value"); /// /// c.set_value("bar"); /// assert_eq!(c.value(), "bar"); /// ``` pubfn set_value<V: Into<Cow<'c, str>>>(&mut self, value: V) { self.value = CookieStr::Concrete(value.into())
}
/// Sets the value of `http_only` in `self` to `value`. If `value` is /// `None`, the field is unset. /// /// # Example /// /// ``` /// use cookie::Cookie; /// /// let mut c = Cookie::new("name", "value"); /// assert_eq!(c.http_only(), None); /// /// c.set_http_only(true); /// assert_eq!(c.http_only(), Some(true)); /// /// c.set_http_only(false); /// assert_eq!(c.http_only(), Some(false)); /// /// c.set_http_only(None); /// assert_eq!(c.http_only(), None); /// ``` #[inline] pubfn set_http_only<T: Into<Option<bool>>>(&mutself, value: T) { self.http_only = value.into();
}
/// Sets the value of `secure` in `self` to `value`. If `value` is `None`, /// the field is unset. /// /// # Example /// /// ``` /// use cookie::Cookie; /// /// let mut c = Cookie::new("name", "value"); /// assert_eq!(c.secure(), None); /// /// c.set_secure(true); /// assert_eq!(c.secure(), Some(true)); /// /// c.set_secure(false); /// assert_eq!(c.secure(), Some(false)); /// /// c.set_secure(None); /// assert_eq!(c.secure(), None); /// ``` #[inline] pubfn set_secure<T: Into<Option<bool>>>(&mutself, value: T) { self.secure = value.into();
}
/// Sets the value of `same_site` in `self` to `value`. If `value` is /// `None`, the field is unset. If `value` is `SameSite::None`, the "Secure" /// flag will be set when the cookie is written out unless `secure` is /// explicitly set to `false` via [`Cookie::set_secure()`] or the equivalent /// builder method. /// /// [HTTP draft]: https://tools.ietf.org/html/draft-west-cookie-incrementalism-00 /// /// # Example /// /// ``` /// use cookie::{Cookie, SameSite}; /// /// let mut c = Cookie::new("name", "value"); /// assert_eq!(c.same_site(), None); /// /// c.set_same_site(SameSite::None); /// assert_eq!(c.same_site(), Some(SameSite::None)); /// assert_eq!(c.to_string(), "name=value; SameSite=None; Secure"); /// /// c.set_secure(false); /// assert_eq!(c.to_string(), "name=value; SameSite=None"); /// /// let mut c = Cookie::new("name", "value"); /// assert_eq!(c.same_site(), None); /// /// c.set_same_site(SameSite::Strict); /// assert_eq!(c.same_site(), Some(SameSite::Strict)); /// assert_eq!(c.to_string(), "name=value; SameSite=Strict"); /// /// c.set_same_site(None); /// assert_eq!(c.same_site(), None); /// assert_eq!(c.to_string(), "name=value"); /// ``` #[inline] pubfn set_same_site<T: Into<Option<SameSite>>>(&mutself, value: T) { self.same_site = value.into();
}
/// Sets the value of `max_age` in `self` to `value`. If `value` is `None`, /// the field is unset. /// /// # Example /// /// ```rust /// # extern crate cookie; /// use cookie::Cookie; /// use cookie::time::Duration; /// /// # fn main() { /// let mut c = Cookie::new("name", "value"); /// assert_eq!(c.max_age(), None); /// /// c.set_max_age(Duration::hours(10)); /// assert_eq!(c.max_age(), Some(Duration::hours(10))); /// /// c.set_max_age(None); /// assert!(c.max_age().is_none()); /// # } /// ``` #[inline] pubfn set_max_age<D: Into<Option<Duration>>>(&mutself, value: D) { self.max_age = value.into();
}
/// Sets the `path` of `self` to `path`. /// /// # Example /// /// ```rust /// use cookie::Cookie; /// /// let mut c = Cookie::new("name", "value"); /// assert_eq!(c.path(), None); /// /// c.set_path("/"); /// assert_eq!(c.path(), Some("/")); /// ``` pubfn set_path<P: Into<Cow<'c, str>>>(&mut self, path: P) { self.path = Some(CookieStr::Concrete(path.into()));
}
/// Unsets the `path` of `self`. /// /// # Example /// /// ``` /// use cookie::Cookie; /// /// let mut c = Cookie::new("name", "value"); /// assert_eq!(c.path(), None); /// /// c.set_path("/"); /// assert_eq!(c.path(), Some("/")); /// /// c.unset_path(); /// assert_eq!(c.path(), None); /// ``` pubfn unset_path(&mutself) { self.path = None;
}
/// Sets the `domain` of `self` to `domain`. /// /// # Example /// /// ``` /// use cookie::Cookie; /// /// let mut c = Cookie::new("name", "value"); /// assert_eq!(c.domain(), None); /// /// c.set_domain("rust-lang.org"); /// assert_eq!(c.domain(), Some("rust-lang.org")); /// ``` pubfn set_domain<D: Into<Cow<'c, str>>>(&mut self, domain: D) { self.domain = Some(CookieStr::Concrete(domain.into()));
}
/// Unsets the `domain` of `self`. /// /// # Example /// /// ``` /// use cookie::Cookie; /// /// let mut c = Cookie::new("name", "value"); /// assert_eq!(c.domain(), None); /// /// c.set_domain("rust-lang.org"); /// assert_eq!(c.domain(), Some("rust-lang.org")); /// /// c.unset_domain(); /// assert_eq!(c.domain(), None); /// ``` pubfn unset_domain(&mutself) { self.domain = None;
}
/// Sets the expires field of `self` to `time`. If `time` is `None`, an /// expiration of [`Session`](Expiration::Session) is set. /// /// # Example /// /// ``` /// # extern crate cookie; /// use cookie::{Cookie, Expiration}; /// use cookie::time::{Duration, OffsetDateTime}; /// /// let mut c = Cookie::new("name", "value"); /// assert_eq!(c.expires(), None); /// /// let mut now = OffsetDateTime::now_utc(); /// now += Duration::weeks(52); /// /// c.set_expires(now); /// assert!(c.expires().is_some()); /// /// c.set_expires(None); /// assert_eq!(c.expires(), Some(Expiration::Session)); /// ``` pubfn set_expires<T: Into<Expiration>>(&mutself, time: T) { static MAX_DATETIME: OffsetDateTime = datetime!(9999-12-3123:59:59.999_999 UTC);
// RFC 6265 requires dates not to exceed 9999 years. self.expires = Some(time.into()
.map(|time| std::cmp::min(time, MAX_DATETIME)));
}
/// Unsets the `expires` of `self`. /// /// # Example /// /// ``` /// use cookie::{Cookie, Expiration}; /// /// let mut c = Cookie::new("name", "value"); /// assert_eq!(c.expires(), None); /// /// c.set_expires(None); /// assert_eq!(c.expires(), Some(Expiration::Session)); /// /// c.unset_expires(); /// assert_eq!(c.expires(), None); /// ``` pubfn unset_expires(&mutself) { self.expires = None;
}
/// Makes `self` a "permanent" cookie by extending its expiration and max /// age 20 years into the future. /// /// # Example /// /// ```rust /// # extern crate cookie; /// use cookie::Cookie; /// use cookie::time::Duration; /// /// # fn main() { /// let mut c = Cookie::new("foo", "bar"); /// assert!(c.expires().is_none()); /// assert!(c.max_age().is_none()); /// /// c.make_permanent(); /// assert!(c.expires().is_some()); /// assert_eq!(c.max_age(), Some(Duration::days(365 * 20))); /// # } /// ``` pubfn make_permanent(&mutself) { let twenty_years = Duration::days(365 * 20); self.set_max_age(twenty_years); self.set_expires(OffsetDateTime::now_utc() + twenty_years);
}
/// Make `self` a "removal" cookie by clearing its value, setting a max-age /// of `0`, and setting an expiration date far in the past. /// /// # Example /// /// ```rust /// # extern crate cookie; /// use cookie::Cookie; /// use cookie::time::Duration; /// /// # fn main() { /// let mut c = Cookie::new("foo", "bar"); /// c.make_permanent(); /// assert_eq!(c.max_age(), Some(Duration::days(365 * 20))); /// assert_eq!(c.value(), "bar"); /// /// c.make_removal(); /// assert_eq!(c.value(), ""); /// assert_eq!(c.max_age(), Some(Duration::ZERO)); /// # } /// ``` pubfn make_removal(&mutself) { self.set_value(""); self.set_max_age(Duration::seconds(0)); self.set_expires(OffsetDateTime::now_utc() - Duration::days(365));
}
iflet Some(time) = self.expires_datetime() { let time = time.to_offset(UtcOffset::UTC);
write!(f, "; Expires={}", time.format(&crate::parse::FMT1).map_err(|_| fmt::Error)?)?;
}
Ok(())
}
/// Returns the name of `self` as a string slice of the raw string `self` /// was originally parsed from. If `self` was not originally parsed from a /// raw string, returns `None`. /// /// This method differs from [`Cookie::name()`] in that it returns a string /// with the same lifetime as the originally parsed string. This lifetime /// may outlive `self`. If a longer lifetime is not required, or you're /// unsure if you need a longer lifetime, use [`Cookie::name()`]. /// /// # Example /// /// ``` /// use cookie::Cookie; /// /// let cookie_string = format!("{}={}", "foo", "bar"); /// /// // `c` will be dropped at the end of the scope, but `name` will live on /// let name = { /// let c = Cookie::parse(cookie_string.as_str()).unwrap(); /// c.name_raw() /// }; /// /// assert_eq!(name, Some("foo")); /// ``` #[inline] pubfn name_raw(&self) -> Option<&'c str> { self.cookie_string.as_ref()
.and_then(|s| self.name.to_raw_str(s))
}
/// Returns the value of `self` as a string slice of the raw string `self` /// was originally parsed from. If `self` was not originally parsed from a /// raw string, returns `None`. /// /// This method differs from [`Cookie::value()`] in that it returns a /// string with the same lifetime as the originally parsed string. This /// lifetime may outlive `self`. If a longer lifetime is not required, or /// you're unsure if you need a longer lifetime, use [`Cookie::value()`]. /// /// # Example /// /// ``` /// use cookie::Cookie; /// /// let cookie_string = format!("{}={}", "foo", "bar"); /// /// // `c` will be dropped at the end of the scope, but `value` will live on /// let value = { /// let c = Cookie::parse(cookie_string.as_str()).unwrap(); /// c.value_raw() /// }; /// /// assert_eq!(value, Some("bar")); /// ``` #[inline] pubfn value_raw(&self) -> Option<&'c str> { self.cookie_string.as_ref()
.and_then(|s| self.value.to_raw_str(s))
}
/// Returns the `Path` of `self` as a string slice of the raw string `self` /// was originally parsed from. If `self` was not originally parsed from a /// raw string, or if `self` doesn't contain a `Path`, or if the `Path` has /// changed since parsing, returns `None`. /// /// This method differs from [`Cookie::path()`] in that it returns a /// string with the same lifetime as the originally parsed string. This /// lifetime may outlive `self`. If a longer lifetime is not required, or /// you're unsure if you need a longer lifetime, use [`Cookie::path()`]. /// /// # Example /// /// ``` /// use cookie::Cookie; /// /// let cookie_string = format!("{}={}; Path=/", "foo", "bar"); /// /// // `c` will be dropped at the end of the scope, but `path` will live on /// let path = { /// let c = Cookie::parse(cookie_string.as_str()).unwrap(); /// c.path_raw() /// }; /// /// assert_eq!(path, Some("/")); /// ``` #[inline] pubfn path_raw(&self) -> Option<&'c str> { match (self.path.as_ref(), self.cookie_string.as_ref()) {
(Some(path), Some(string)) => path.to_raw_str(string),
_ => None,
}
}
/// Returns the `Domain` of `self` as a string slice of the raw string /// `self` was originally parsed from. If `self` was not originally parsed /// from a raw string, or if `self` doesn't contain a `Domain`, or if the /// `Domain` has changed since parsing, returns `None`. /// /// This method differs from [`Cookie::domain()`] in that it returns a /// string with the same lifetime as the originally parsed string. This /// lifetime may outlive `self` struct. If a longer lifetime is not /// required, or you're unsure if you need a longer lifetime, use /// [`Cookie::domain()`]. /// /// # Example /// /// ``` /// use cookie::Cookie; /// /// let cookie_string = format!("{}={}; Domain=crates.io", "foo", "bar"); /// /// //`c` will be dropped at the end of the scope, but `domain` will live on /// let domain = { /// let c = Cookie::parse(cookie_string.as_str()).unwrap(); /// c.domain_raw() /// }; /// /// assert_eq!(domain, Some("crates.io")); /// ``` #[inline] pubfn domain_raw(&self) -> Option<&'c str> { match (self.domain.as_ref(), self.cookie_string.as_ref()) {
(Some(domain), Some(string)) => domain.to_raw_str(string),
_ => None,
}
}
/// Wraps `self` in an encoded [`Display`]: a cost-free wrapper around /// `Cookie` whose [`fmt::Display`] implementation percent-encodes the name /// and value of the wrapped `Cookie`. /// /// The returned structure can be chained with [`Display::stripped()`] to /// display only the name and value. /// /// # Example /// /// ```rust /// use cookie::Cookie; /// /// let mut c = Cookie::build("my name", "this; value?").secure(true).finish(); /// assert_eq!(&c.encoded().to_string(), "my%20name=this%3B%20value%3F; Secure"); /// assert_eq!(&c.encoded().stripped().to_string(), "my%20name=this%3B%20value%3F"); /// ``` #[cfg(feature = "percent-encode")] #[cfg_attr(all(nightly, doc), doc(cfg(feature = "percent-encode")))] #[inline(always)] pubfn encoded<'a>(&'a self) -> Display<'a, 'c> {
Display::new_encoded(self)
}
/// Wraps `self` in a stripped `Display`]: a cost-free wrapper around /// `Cookie` whose [`fmt::Display`] implementation prints only the `name` /// and `value` of the wrapped `Cookie`. /// /// The returned structure can be chained with [`Display::encoded()`] to /// encode the name and value. /// /// # Example /// /// ```rust /// use cookie::Cookie; /// /// let mut c = Cookie::build("key?", "value").secure(true).path("/").finish(); /// assert_eq!(&c.stripped().to_string(), "key?=value"); #[cfg_attr(feature = "percent-encode", doc = r##" // Note: `encoded()` is only available when `percent-encode` is enabled.
assert_eq!(&c.stripped().encoded().to_string(), "key%3F=value"); #"##)] /// ``` #[inline(always)] pubfn stripped<'a>(&'a self) -> Display<'a, 'c> {
Display::new_stripped(self)
}
}
#[cfg(feature = "percent-encode")] mod encoding { use percent_encoding::{AsciiSet, CONTROLS};
/// Percent-encode a cookie name or value with the proper encoding set. pubfn encode(string: &str) -> impl std::fmt::Display + '_ {
percent_encoding::percent_encode(string.as_bytes(), COOKIE)
}
}
/// Wrapper around `Cookie` whose `Display` implementation either /// percent-encodes the cookie's name and value, skips displaying the cookie's /// parameters (only displaying it's name and value), or both. /// /// A value of this type can be obtained via [`Cookie::encoded()`] and /// [`Cookie::stripped()`], or an arbitrary chaining of the two methods. This /// type should only be used for its `Display` implementation. /// /// # Example /// /// ```rust /// use cookie::Cookie; /// /// let c = Cookie::build("my name", "this; value%?").secure(true).finish(); /// assert_eq!(&c.stripped().to_string(), "my name=this; value%?"); #[cfg_attr(feature = "percent-encode", doc = r##" // Note: `encoded()` is only available when `percent-encode` is enabled.
assert_eq!(&c.encoded().to_string(), "my%20name=this%3B%20value%25%3F; Secure");
assert_eq!(&c.stripped().encoded().to_string(), "my%20name=this%3B%20value%25%3F");
assert_eq!(&c.encoded().stripped().to_string(), "my%20name=this%3B%20value%25%3F"); "##)] /// ``` pubstruct Display<'a, 'c: 'a> {
cookie: &'a Cookie<'c>, #[cfg(feature = "percent-encode")]
encode: bool,
strip: bool,
}
impl<'a, 'c: 'a> fmt::Display for Display<'a, 'c> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { #[cfg(feature = "percent-encode")] { ifself.encode { let name = encoding::encode(self.cookie.name()); let value = encoding::encode(self.cookie.value());
write!(f, "{}={}", name, value)?;
} else {
write!(f, "{}={}", self.cookie.name(), self.cookie.value())?;
}
}
¤ 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.0.30Bemerkung:
(vorverarbeitet am 2026-06-18)
¤
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.