Struct cookie::CookieJar

source ·
pub struct CookieJar {
    original_cookies: HashSet<DeltaCookie>,
    delta_cookies: HashSet<DeltaCookie>,
}
Expand description

A collection of cookies that tracks its modifications.

A CookieJar provides storage for any number of cookies. Any changes made to the jar are tracked; the changes can be retrieved via the delta method which returns an iterator over the changes.

§Usage

A jar’s life begins via CookieJar::new() and calls to add_original():

use cookie::{Cookie, CookieJar};

let mut jar = CookieJar::new();
jar.add_original(("name", "value"));
jar.add_original(("second", "another"));
jar.add_original(Cookie::build(("third", "again")).path("/"));

Cookies can be added via CookieJar::add() and removed via CookieJar::remove(). Note that any T: Into<Cookie> can be passed into these methods; see Cookie::build() for a table of implementing types.

Finally, cookies can be retrieved with CookieJar::get().

let mut jar = CookieJar::new();
jar.add(("a", "one"));
jar.add(("b", "two"));

assert_eq!(jar.get("a").map(|c| c.value()), Some("one"));
assert_eq!(jar.get("b").map(|c| c.value()), Some("two"));

jar.remove("b");
assert!(jar.get("b").is_none());

§Deltas

A jar keeps track of any modifications made to it over time. The modifications are recorded as cookies. The modifications can be retrieved via delta. Any new Cookie added to a jar via add results in the same Cookie appearing in the delta; cookies added via add_original do not count towards the delta. Any original cookie that is removed from a jar results in a “removal” cookie appearing in the delta. A “removal” cookie is a cookie that a server sends so that the cookie is removed from the client’s machine.

Deltas are typically used to create Set-Cookie headers corresponding to the changes made to a cookie jar over a period of time.

let mut jar = CookieJar::new();

// original cookies don't affect the delta
jar.add_original(("original", "value"));
assert_eq!(jar.delta().count(), 0);

// new cookies result in an equivalent `Cookie` in the delta
jar.add(("a", "one"));
jar.add(("b", "two"));
assert_eq!(jar.delta().count(), 2);

// removing an original cookie adds a "removal" cookie to the delta
jar.remove("original");
assert_eq!(jar.delta().count(), 3);

// removing a new cookie that was added removes that `Cookie` from the delta
jar.remove("a");
assert_eq!(jar.delta().count(), 2);

Fields§

§original_cookies: HashSet<DeltaCookie>§delta_cookies: HashSet<DeltaCookie>

Implementations§

source§

impl CookieJar

source

pub fn new() -> CookieJar

Creates an empty cookie jar.

§Example
use cookie::CookieJar;

let jar = CookieJar::new();
assert_eq!(jar.iter().count(), 0);
source

pub fn get(&self, name: &str) -> Option<&Cookie<'static>>

Returns a reference to the Cookie inside this jar with the name name. If no such cookie exists, returns None.

§Example
use cookie::{CookieJar, Cookie};

let mut jar = CookieJar::new();
assert!(jar.get("name").is_none());

jar.add(("name", "value"));
assert_eq!(jar.get("name").map(|c| c.value()), Some("value"));
source

pub fn add_original<C: Into<Cookie<'static>>>(&mut self, cookie: C)

Adds an “original” cookie to this jar. If an original cookie with the same name already exists, it is replaced with cookie. Cookies added with add take precedence and are not replaced by this method.

Adding an original cookie does not affect the delta computation. This method is intended to be used to seed the cookie jar with cookies received from a client’s HTTP message.

For accurate delta computations, this method should not be called after calling remove.

§Example
use cookie::{CookieJar, Cookie};

let mut jar = CookieJar::new();
jar.add_original(("name", "value"));
jar.add_original(("second", "two"));

assert_eq!(jar.get("name").map(|c| c.value()), Some("value"));
assert_eq!(jar.get("second").map(|c| c.value()), Some("two"));
assert_eq!(jar.iter().count(), 2);
assert_eq!(jar.delta().count(), 0);
source

pub fn add<C: Into<Cookie<'static>>>(&mut self, cookie: C)

Adds cookie to this jar. If a cookie with the same name already exists, it is replaced with cookie.

§Example
use cookie::{CookieJar, Cookie};

let mut jar = CookieJar::new();
jar.add(("name", "value"));
jar.add(("second", "two"));

assert_eq!(jar.get("name").map(|c| c.value()), Some("value"));
assert_eq!(jar.get("second").map(|c| c.value()), Some("two"));
assert_eq!(jar.iter().count(), 2);
assert_eq!(jar.delta().count(), 2);
source

pub fn remove<C: Into<Cookie<'static>>>(&mut self, cookie: C)

Removes cookie from this jar. If an original cookie with the same name as cookie is present in the jar, a removal cookie will be present in the delta computation. To properly generate the removal cookie, cookie must contain the same path and domain as the cookie that was initially set.

A “removal” cookie is a cookie that has the same name as the original cookie but has an empty value, a max-age of 0, and an expiration date far in the past. See also Cookie::make_removal().

§Example

Removing an original cookie results in a removal cookie:

use cookie::{CookieJar, Cookie};
use cookie::time::Duration;

let mut jar = CookieJar::new();

// Assume this cookie originally had a path of "/" and domain of "a.b".
jar.add_original(("name", "value"));

// If the path and domain were set, they must be provided to `remove`.
jar.remove(Cookie::build("name").path("/").domain("a.b"));

// The delta will contain the removal cookie.
let delta: Vec<_> = jar.delta().collect();
assert_eq!(delta.len(), 1);
assert_eq!(delta[0].name(), "name");
assert_eq!(delta[0].max_age(), Some(Duration::seconds(0)));

Removing a new cookie does not result in a removal cookie unless there’s an original cookie with the same name:

use cookie::{CookieJar, Cookie};

let mut jar = CookieJar::new();
jar.add(("name", "value"));
assert_eq!(jar.delta().count(), 1);

jar.remove("name");
assert_eq!(jar.delta().count(), 0);

jar.add_original(("name", "value"));
jar.add(("name", "value"));
assert_eq!(jar.delta().count(), 1);

jar.remove("name");
assert_eq!(jar.delta().count(), 1);
source

pub fn force_remove<N: AsRef<str>>(&mut self, name: N)

Removes cookie from this jar completely.

This method differs from remove in that no delta cookie is created under any condition. Thus, no path or domain are needed: only the cookie’s name. Neither the delta nor iter methods will return a cookie that is removed using this method.

§Example

Removing an original cookie; no removal cookie is generated:

use cookie::{CookieJar, Cookie};
use cookie::time::Duration;

let mut jar = CookieJar::new();

// Add an original cookie and a new cookie.
jar.add_original(("name", "value"));
jar.add(("key", "value"));
assert_eq!(jar.delta().count(), 1);
assert_eq!(jar.iter().count(), 2);

// Now force remove the original cookie.
jar.force_remove("name");
assert_eq!(jar.delta().count(), 1);
assert_eq!(jar.iter().count(), 1);

// Now force remove the new cookie. `to_string()` for illustration only.
jar.force_remove("key".to_string());
assert_eq!(jar.delta().count(), 0);
assert_eq!(jar.iter().count(), 0);
source

pub fn reset_delta(&mut self)

Removes all delta cookies, i.e. all cookies not added via CookieJar::add_original(), from this CookieJar. This undoes any changes from CookieJar::add() and CookieJar::remove() operations.

§Example
use cookie::{CookieJar, Cookie};

let mut jar = CookieJar::new();

// Only original cookies will remain after calling `reset_delta`.
jar.add_original(("name", "value"));
jar.add_original(("language", "Rust"));

// These operations, represented by delta cookies, will be reset.
jar.add(("language", "C++"));
jar.remove("name");

// All is normal.
assert_eq!(jar.get("name"), None);
assert_eq!(jar.get("language").map(Cookie::value), Some("C++"));
assert_eq!(jar.iter().count(), 1);
assert_eq!(jar.delta().count(), 2);

// Resetting undoes delta operations.
jar.reset_delta();
assert_eq!(jar.get("name").map(Cookie::value), Some("value"));
assert_eq!(jar.get("language").map(Cookie::value), Some("Rust"));
assert_eq!(jar.iter().count(), 2);
assert_eq!(jar.delta().count(), 0);
source

pub fn delta(&self) -> Delta<'_>

Returns an iterator over cookies that represent the changes to this jar over time. These cookies can be rendered directly as Set-Cookie header values to affect the changes made to this jar on the client.

§Example
use cookie::{CookieJar, Cookie};

let mut jar = CookieJar::new();
jar.add_original(("name", "value"));
jar.add_original(("second", "two"));

// Add new cookies.
jar.add(("new", "third"));
jar.add(("another", "fourth"));
jar.add(("yac", "fifth"));

// Remove some cookies.
jar.remove(("name"));
jar.remove(("another"));

// Delta contains two new cookies ("new", "yac") and a removal ("name").
assert_eq!(jar.delta().count(), 3);
source

pub fn iter(&self) -> Iter<'_>

Returns an iterator over all of the cookies present in this jar.

§Example
use cookie::{CookieJar, Cookie};

let mut jar = CookieJar::new();

jar.add_original(("name", "value"));
jar.add_original(("second", "two"));

jar.add(("new", "third"));
jar.add(("another", "fourth"));
jar.add(("yac", "fifth"));

jar.remove("name");
jar.remove("another");

// There are three cookies in the jar: "second", "new", and "yac".
for cookie in jar.iter() {
    match cookie.name() {
        "second" => assert_eq!(cookie.value(), "two"),
        "new" => assert_eq!(cookie.value(), "third"),
        "yac" => assert_eq!(cookie.value(), "fifth"),
        _ => unreachable!("there are only three cookies in the jar")
    }
}
source

pub fn prefixed<'a, P: Prefix>(&'a self, prefix: P) -> PrefixedJar<P, &'a Self>

Returns a read-only PrefixedJar with self as its parent jar that prefixes the name of cookies with prefix. Any retrievals from the child jar will be made from the parent jar.

Note: Cookie prefixes are specified in an HTTP draft! Their meaning and definition are subject to change.

§Example
use cookie::CookieJar;
use cookie::prefix::{Host, Secure};

// Add a `Host` prefixed cookie.
let mut jar = CookieJar::new();
jar.prefixed_mut(Host).add(("h0st", "value"));
jar.prefixed_mut(Secure).add(("secur3", "value"));

// The cookie's name is prefixed in the parent jar.
assert!(matches!(jar.get("h0st"), None));
assert!(matches!(jar.get("__Host-h0st"), Some(_)));
assert!(matches!(jar.get("secur3"), None));
assert!(matches!(jar.get("__Secure-secur3"), Some(_)));

// The prefixed jar automatically removes the prefix.
assert_eq!(jar.prefixed(Host).get("h0st").unwrap().name(), "h0st");
assert_eq!(jar.prefixed(Host).get("h0st").unwrap().value(), "value");
assert_eq!(jar.prefixed(Secure).get("secur3").unwrap().name(), "secur3");
assert_eq!(jar.prefixed(Secure).get("secur3").unwrap().value(), "value");

// Only the correct prefixed jar retrieves the cookie.
assert!(matches!(jar.prefixed(Host).get("secur3"), None));
assert!(matches!(jar.prefixed(Secure).get("h0st"), None));
source

pub fn prefixed_mut<'a, P: Prefix>( &'a mut self, prefix: P, ) -> PrefixedJar<P, &'a mut Self>

Returns a read/write PrefixedJar with self as its parent jar that prefixes the name of cookies with prefix and makes the cookie conform to the prefix’s requirements. This means that added cookies:

  1. Have the Prefix::PREFIX prepended to their name.
  2. Modify the cookie via Prefix::conform() so that it conforms to the prefix’s requirements.

Any modifications to the child jar will be reflected on the parent jar, and any retrievals from the child jar will be made from the parent jar.

Note: Cookie prefixes are specified in an HTTP draft! Their meaning and definition are subject to change.

§Example
use cookie::CookieJar;
use cookie::prefix::{Host, Secure};

// Add some prefixed cookies.
let mut jar = CookieJar::new();
jar.prefixed_mut(Host).add(("one", "1"));
jar.prefixed_mut(Secure).add((2.to_string(), "2"));
jar.prefixed_mut(Host).add((format!("{:0b}", 3), "0b11"));

// Fetch cookies with either `prefixed()` or `prefixed_mut()`.
assert_eq!(jar.prefixed(Host).get("one").unwrap().value(), "1");
assert_eq!(jar.prefixed(Secure).get("2").unwrap().value(), "2");
assert_eq!(jar.prefixed_mut(Host).get("11").unwrap().value(), "0b11");

// Remove cookies.
jar.prefixed_mut(Host).remove("one");
assert!(jar.prefixed(Host).get("one").is_none());

Trait Implementations§

source§

impl Clone for CookieJar

source§

fn clone(&self) -> CookieJar

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for CookieJar

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Default for CookieJar

source§

fn default() -> CookieJar

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> ToOwned for T
where T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.