pub struct CookieJar { /* private fields */ }
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);
Implementations§
source§impl CookieJar
impl CookieJar
sourcepub fn new() -> CookieJar
pub fn new() -> CookieJar
Creates an empty cookie jar.
§Example
use cookie::CookieJar;
let jar = CookieJar::new();
assert_eq!(jar.iter().count(), 0);
sourcepub fn get(&self, name: &str) -> Option<&Cookie<'static>>
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"));
sourcepub fn add_original<C: Into<Cookie<'static>>>(&mut self, cookie: C)
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);
sourcepub fn add<C: Into<Cookie<'static>>>(&mut self, cookie: C)
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);
sourcepub fn remove<C: Into<Cookie<'static>>>(&mut self, cookie: C)
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);
sourcepub fn force_remove<N: AsRef<str>>(&mut self, name: N)
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);
sourcepub fn reset_delta(&mut self)
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);
sourcepub fn delta(&self) -> Delta<'_> ⓘ
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);
sourcepub fn iter(&self) -> Iter<'_> ⓘ
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")
}
}
sourcepub fn private<'a>(&'a self, key: &Key) -> PrivateJar<&'a Self>
Available on crate feature private
only.
pub fn private<'a>(&'a self, key: &Key) -> PrivateJar<&'a Self>
private
only.Returns a read-only PrivateJar
with self
as its parent jar using the
key key
to verify/decrypt cookies retrieved from the child jar. Any
retrievals from the child jar will be made from the parent jar.
§Example
use cookie::{Cookie, CookieJar, Key};
// Generate a secure key.
let key = Key::generate();
// Add a private (signed + encrypted) cookie.
let mut jar = CookieJar::new();
jar.private_mut(&key).add(("private", "text"));
// The cookie's contents are encrypted.
assert_ne!(jar.get("private").unwrap().value(), "text");
// They can be decrypted and verified through the child jar.
assert_eq!(jar.private(&key).get("private").unwrap().value(), "text");
// A tampered with cookie does not validate but still exists.
let mut cookie = jar.get("private").unwrap().clone();
jar.add(("private", cookie.value().to_string() + "!"));
assert!(jar.private(&key).get("private").is_none());
assert!(jar.get("private").is_some());
sourcepub fn private_mut<'a>(&'a mut self, key: &Key) -> PrivateJar<&'a mut Self>
Available on crate feature private
only.
pub fn private_mut<'a>(&'a mut self, key: &Key) -> PrivateJar<&'a mut Self>
private
only.Returns a read/write PrivateJar
with self
as its parent jar using
the key key
to sign/encrypt and verify/decrypt cookies added/retrieved
from the child jar.
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.
§Example
use cookie::{Cookie, CookieJar, Key};
// Generate a secure key.
let key = Key::generate();
// Add a private (signed + encrypted) cookie.
let mut jar = CookieJar::new();
jar.private_mut(&key).add(("private", "text"));
// Remove a cookie using the child jar.
jar.private_mut(&key).remove("private");
sourcepub fn signed<'a>(&'a self, key: &Key) -> SignedJar<&'a Self>
Available on crate feature signed
only.
pub fn signed<'a>(&'a self, key: &Key) -> SignedJar<&'a Self>
signed
only.Returns a read-only SignedJar
with self
as its parent jar using the
key key
to verify cookies retrieved from the child jar. Any retrievals
from the child jar will be made from the parent jar.
§Example
use cookie::{Cookie, CookieJar, Key};
// Generate a secure key.
let key = Key::generate();
// Add a signed cookie.
let mut jar = CookieJar::new();
jar.signed_mut(&key).add(("signed", "text"));
// The cookie's contents are signed but still in plaintext.
assert_ne!(jar.get("signed").unwrap().value(), "text");
assert!(jar.get("signed").unwrap().value().contains("text"));
// They can be verified through the child jar.
assert_eq!(jar.signed(&key).get("signed").unwrap().value(), "text");
// A tampered with cookie does not validate but still exists.
let mut cookie = jar.get("signed").unwrap().clone();
jar.add(("signed", cookie.value().to_string() + "!"));
assert!(jar.signed(&key).get("signed").is_none());
assert!(jar.get("signed").is_some());
sourcepub fn signed_mut<'a>(&'a mut self, key: &Key) -> SignedJar<&'a mut Self>
Available on crate feature signed
only.
pub fn signed_mut<'a>(&'a mut self, key: &Key) -> SignedJar<&'a mut Self>
signed
only.Returns a read/write SignedJar
with self
as its parent jar using the
key key
to sign/verify cookies added/retrieved from the child jar.
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.
§Example
use cookie::{CookieJar, Key};
// Generate a secure key.
let key = Key::generate();
// Add a signed cookie.
let mut jar = CookieJar::new();
jar.signed_mut(&key).add(("signed", "text"));
// Remove a cookie.
jar.signed_mut(&key).remove("signed");
sourcepub fn prefixed<'a, P: Prefix>(&'a self, prefix: P) -> PrefixedJar<P, &'a Self>
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));
sourcepub fn prefixed_mut<'a, P: Prefix>(
&'a mut self,
prefix: P
) -> PrefixedJar<P, &'a mut Self>
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:
- Have the
Prefix::PREFIX
prepended to their name. - 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());