Skip to main content

cookie_store/
lib.rs

1#![cfg_attr(docsrs, feature(doc_cfg))]
2//! # cookie_store
3//! Provides an implementation for storing and retrieving [`Cookie`]s per the path and domain matching
4//! rules specified in [RFC6265](https://datatracker.ietf.org/doc/html/rfc6265).
5//!
6//! ## Example
7//! Please refer to the [reqwest_cookie_store](https://crates.io/crates/reqwest_cookie_store) for
8//! an example of using this library along with [reqwest](https://crates.io/crates/reqwest).
9//!
10//! ## Feature flags
11#![doc = document_features::document_features!()]
12
13pub use ::cookie::{Cookie as RawCookie, ParseError as RawCookieParseError};
14
15mod cookie;
16pub use crate::cookie::Error as CookieError;
17pub use crate::cookie::{Cookie, CookieResult};
18mod cookie_domain;
19pub use crate::cookie_domain::CookieDomain;
20mod cookie_expiration;
21pub use crate::cookie_expiration::CookieExpiration;
22mod cookie_path;
23pub use crate::cookie_path::CookiePath;
24mod cookie_store;
25pub use crate::cookie_store::{CookieStore, StoreAction};
26#[cfg(feature = "serde")]
27pub mod serde;
28mod utils;
29
30#[derive(Debug)]
31pub struct IdnaErrors(idna::Errors);
32
33impl std::fmt::Display for IdnaErrors {
34    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
35        write!(f, "IDNA errors: {:#?}", self.0)
36    }
37}
38
39impl std::error::Error for IdnaErrors {}
40
41impl From<idna::Errors> for IdnaErrors {
42    fn from(e: idna::Errors) -> Self {
43        IdnaErrors(e)
44    }
45}
46
47pub type Error = Box<dyn std::error::Error + Send + Sync>;
48pub type Result<T> = std::result::Result<T, Error>;
49
50#[cfg(feature = "serde")]
51pub(crate) mod rfc3339_fmt {
52
53    pub(crate) const RFC3339_FORMAT: &[time::format_description::FormatItem] =
54        time::macros::format_description!("[year]-[month]-[day]T[hour]:[minute]:[second]Z");
55
56    pub(super) fn serialize<S>(t: &time::OffsetDateTime, serializer: S) -> Result<S::Ok, S::Error>
57    where
58        S: serde::Serializer,
59    {
60        use serde::ser::Error;
61        // An explicit format string is used here, instead of time::format_description::well_known::Rfc3339, to explicitly
62        // utilize the 'Z' terminator instead of +00:00 format for Zulu time.
63        let s = t.format(&RFC3339_FORMAT).map_err(|e| {
64            println!("{e}");
65            S::Error::custom(format!(
66                "Could not parse datetime '{t}' as RFC3339 UTC format: {e}"
67            ))
68        })?;
69        serializer.serialize_str(&s)
70    }
71
72    pub(super) fn deserialize<'de, D>(t: D) -> Result<time::OffsetDateTime, D::Error>
73    where
74        D: serde::Deserializer<'de>,
75    {
76        use serde::{de::Error, Deserialize};
77
78        let s = String::deserialize(t)?;
79        time::OffsetDateTime::parse(&s, &time::format_description::well_known::Rfc3339).map_err(
80            |e| {
81                D::Error::custom(format!(
82                    "Could not parse string '{s}' as RFC3339 UTC format: {e}"
83                ))
84            },
85        )
86    }
87}