in crates/fig_request/src/midway.rs [166:256]
fn parse(cookie_jar: &str) -> Result<Self, MidwayError> {
// The midway cookie is stored in ~/.midway/cookie, and is stored in the "Netscape
// cookiejar format" used by cURL: https://curl.se/docs/http-cookies.html. This format is
// not used by browsers any more, and is mostly now a quirk of cURL. The format is simple
// enough that we can parse it ourselves and then inject cookies into reqwest's cookie
// store.
let mut cookies = Vec::new();
const HTTP_ONLY_PREFIX: &str = "#HttpOnly_";
for line in cookie_jar.lines() {
let line = line.trim_start();
if line.is_empty() {
continue;
}
if line.starts_with('#') && !line.starts_with(HTTP_ONLY_PREFIX) {
continue;
}
let mut fields = line.split('\t');
let domain = fields.next().ok_or_else(|| ErrorKind::parse("cookie domain not set"))?;
let (domain, http_only) = if let Some(domain) = domain.strip_prefix(HTTP_ONLY_PREFIX) {
(domain, true)
} else {
(domain, false)
};
let domain = domain.trim_start_matches('.');
let include_subdomains = fields
.next()
.ok_or_else(|| ErrorKind::parse("cookie domain not set"))
.and_then(|v| match v {
"TRUE" => Ok(true),
"FALSE" => Ok(false),
_ => Err(ErrorKind::parse(
"include subdomains field in midway cookie not TRUE or FALSE",
)),
})?;
let path = fields.next().ok_or_else(|| ErrorKind::parse("https only not set"))?;
let https_only = fields
.next()
.ok_or_else(|| ErrorKind::parse("midway cookie HTTPS only field not set"))
.and_then(|v| match v {
"TRUE" => Ok(true),
"FALSE" => Ok(false),
_ => Err(ErrorKind::parse("HTTPS only field in midway cookie not TRUE or FALSE")),
})?;
let expires = fields
.next()
.ok_or_else(|| ErrorKind::parse("expiry was not set"))
.and_then(|v| {
Ok(std::num::NonZeroI64::new(v.parse().map_err(|_err| {
ErrorKind::ParseError("expiry was not a number".into())
})?))
})?;
let name = fields.next().ok_or_else(|| ErrorKind::parse("cookie name not set"))?;
let value = fields.next().ok_or_else(|| ErrorKind::parse("cookie value not set"))?;
let mut cookie = cookie::CookieBuilder::new(name, value)
.path(path)
.secure(https_only)
.http_only(http_only);
// If the cookie domain field is set does it include subdomains.
if include_subdomains {
cookie = cookie.domain(domain);
}
match expires {
None => {},
Some(ts) => {
cookie = cookie.expires(
time::OffsetDateTime::from_unix_timestamp(ts.get())
.map_err(|_err| ErrorKind::parse("expiry was not a valid Unix timestamp"))?,
);
},
}
let cookie = cookie.build().into_owned();
let url = url::Url::parse(&format!("https://{}{}", domain, cookie.path().unwrap()))
.map_err(|err| ErrorKind::parse(format!("failed to construct URL for cookie domain: {err}")))?;
if let Some(cookie::Expiration::DateTime(ts)) = cookie.expires() {
if ts <= time::OffsetDateTime::now_utc() {
// skip expired cookie
continue;
}
}
cookies.push((url, cookie));
}
Ok(Self { cookies })
}