netscape_cookie_file_parser/cookie.rs
1/// One parsed cookie record from a Netscape cookie file.
2///
3/// String-like fields are byte buffers rather than `String`s because cookie jar
4/// files seen in the wild may contain non-UTF-8 octets.
5#[derive(Debug, Clone, PartialEq, Eq)]
6pub struct Cookie {
7 /// Cookie domain with one leading dot removed, matching curl's behavior.
8 pub domain: Vec<u8>,
9 /// Whether the original tail-match field was `TRUE`, case-insensitively.
10 pub tail_match: bool,
11 /// Sanitized cookie path.
12 ///
13 /// Relative and malformed paths are normalized to `/`; non-root paths have
14 /// one trailing slash removed.
15 pub path: Vec<u8>,
16 /// Whether the original secure field was `TRUE`, case-insensitively.
17 pub secure: bool,
18 /// Expiration timestamp parsed as an unsigned integer.
19 pub expires: u64,
20 /// Raw cookie name bytes.
21 pub name: Vec<u8>,
22 /// Raw cookie value bytes.
23 pub value: Vec<u8>,
24 /// Whether this line used curl's `#HttpOnly_` cookie marker.
25 pub http_only: bool,
26 /// Recognized security prefix in the cookie name.
27 pub prefix: CookiePrefix,
28}
29
30/// Case-sensitive cookie name prefixes recognized by the parser.
31#[derive(Debug, Clone, Copy, PartialEq, Eq)]
32pub enum CookiePrefix {
33 /// No recognized cookie prefix.
34 None,
35 /// Cookie name starts with `__Secure-`.
36 Secure,
37 /// Cookie name starts with `__Host-`.
38 Host,
39}
40
41// The prefix checks are intentionally case-sensitive: cookie prefixes are part
42// of the cookie name contract, not ordinary case-insensitive cookie metadata.
43pub(crate) fn cookie_prefix(name: &[u8]) -> CookiePrefix {
44 if name.starts_with(b"__Secure-") {
45 CookiePrefix::Secure
46 } else if name.starts_with(b"__Host-") {
47 CookiePrefix::Host
48 } else {
49 CookiePrefix::None
50 }
51}