diff --git a/Cargo.toml b/Cargo.toml index d8800ba8..18ce8417 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,6 +32,7 @@ tokio-stream = "0.1" chrono = { version = "0.4.40", default-features = false, features = ["clock"] } chrono-tz = { version = "0.10.4" } jiff = { version = "0.2.10", features = ["tzdb-bundle-always"] } +time = { version = ">=0.3.0, <0.3.52" } arrow = { version = "56" } arrow-array = { version = "56" } arrow-schema = { version = "56" } diff --git a/core/Cargo.toml b/core/Cargo.toml index 8254c20d..def5c132 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -28,6 +28,7 @@ bytes = "1.10.1" base64 = "0.22.1" cookie = "0.18.1" jiff = { workspace = true } +time = { workspace = true } log = { version = "0.4", features = ["kv"] } once_cell = "1.21" parking_lot = "0.12.3" diff --git a/core/src/global_cookie_store.rs b/core/src/global_cookie_store.rs index 15b3c64c..aa2118bb 100644 --- a/core/src/global_cookie_store.rs +++ b/core/src/global_cookie_store.rs @@ -12,11 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -use cookie::Cookie; +use cookie::{Cookie, Expiration}; use reqwest::cookie::CookieStore; use reqwest::header::HeaderValue; use std::collections::HashMap; use std::sync::RwLock; +use time::OffsetDateTime; use url::Url; pub(crate) struct GlobalCookieStore { @@ -31,6 +32,16 @@ impl GlobalCookieStore { } } +fn is_expired(cookie: &Cookie<'_>) -> bool { + cookie + .max_age() + .is_some_and(|age| age <= time::Duration::ZERO) + || matches!( + cookie.expires(), + Some(Expiration::DateTime(expires)) if expires <= OffsetDateTime::now_utc() + ) +} + impl CookieStore for GlobalCookieStore { fn set_cookies(&self, cookie_headers: &mut dyn Iterator, _url: &Url) { let iter = cookie_headers @@ -39,12 +50,18 @@ impl CookieStore for GlobalCookieStore { let mut guard = self.cookies.write().unwrap(); for cookie in iter { - guard.insert(cookie.name().to_string(), cookie); + let name = cookie.name().to_string(); + if is_expired(&cookie) { + guard.remove(&name); + } else { + guard.insert(name, cookie); + } } } fn cookies(&self, _url: &Url) -> Option { - let guard = self.cookies.read().unwrap(); + let mut guard = self.cookies.write().unwrap(); + guard.retain(|_, cookie| !is_expired(cookie)); let s: String = guard .values() .map(|cookie| cookie.name_value())