Skip to main content

netscape_cookie_file_parser/
lib.rs

1//! Parser for Netscape/curl cookie jar files.
2//!
3//! Netscape cookie files are line-oriented. Each cookie line contains seven
4//! tab-separated fields: domain, tail-match flag, path, secure flag, expires,
5//! name, and value. This crate keeps cookie data as raw bytes so non-UTF-8
6//! cookie names, values, paths, and domains can round-trip through the parser.
7//!
8//! Empty lines and ordinary `#` comments are skipped. curl's `#HttpOnly_`
9//! extension is treated as metadata on the cookie rather than as a comment.
10//!
11//! ```
12//! use netscape_cookie_file_parser::{parse_line, CookiePrefix};
13//!
14//! let cookie = parse_line("#HttpOnly_.example.com\tTRUE\t/\tTRUE\t0\t__Secure-SID\tabc")
15//!     .unwrap()
16//!     .unwrap();
17//!
18//! assert_eq!(cookie.domain, b"example.com");
19//! assert!(cookie.http_only);
20//! assert_eq!(cookie.prefix, CookiePrefix::Secure);
21//! ```
22
23use std::io::BufRead;
24
25mod cookie;
26mod error;
27mod parser;
28#[cfg(test)]
29mod tests;
30
31pub use cookie::{Cookie, CookiePrefix};
32pub use error::{ParseError, ParseErrorKind};
33pub use parser::NetscapeCookieParser;
34
35/// Parses all valid cookie lines from a buffered reader.
36///
37/// The first malformed cookie line or I/O error stops parsing and returns a
38/// [`ParseError`] with the 1-based line number.
39pub fn parse<R: BufRead>(reader: R) -> Result<Vec<Cookie>, ParseError> {
40    NetscapeCookieParser::new(reader).collect()
41}
42
43/// Parses all valid cookie lines and skips malformed cookie records.
44///
45/// I/O errors are still returned because the parser cannot safely continue once
46/// the underlying reader fails.
47pub fn parse_lossy<R: BufRead>(reader: R) -> Result<Vec<Cookie>, ParseError> {
48    let mut cookies = Vec::new();
49
50    for result in NetscapeCookieParser::new(reader) {
51        match result {
52            Ok(cookie) => cookies.push(cookie),
53            Err(error) if matches!(error.kind, ParseErrorKind::Io(_)) => return Err(error),
54            Err(_) => {}
55        }
56    }
57
58    Ok(cookies)
59}
60
61/// Parses one Netscape cookie file line.
62///
63/// Returns `Ok(None)` for blank lines, ordinary comments, and `#HttpOnly_`
64/// lines whose payload is still a comment.
65pub fn parse_line(line: impl AsRef<[u8]>) -> Result<Option<Cookie>, ParseErrorKind> {
66    parser::parse_line_inner(line.as_ref())
67}