From c2bbd57accf4e4cc98822ee6b2547a40d452cbac Mon Sep 17 00:00:00 2001 From: Martin Algesten Date: Fri, 30 Oct 2020 06:38:23 +0100 Subject: [PATCH] Agent::cookie_store to persist cookies --- src/agent.rs | 28 +++++++++++++++++++++++++++- src/cookies.rs | 21 ++++++++++++++++++++- 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/src/agent.rs b/src/agent.rs index 65a3af2..3d78dba 100644 --- a/src/agent.rs +++ b/src/agent.rs @@ -7,7 +7,10 @@ use crate::resolve::{ArcResolver, StdResolver}; use std::time::Duration; #[cfg(feature = "cookies")] -use {crate::cookies::CookieTin, cookie_store::CookieStore}; +use { + crate::cookies::{CookieStoreGuard, CookieTin}, + cookie_store::CookieStore, +}; #[derive(Debug)] pub struct AgentBuilder { @@ -131,6 +134,29 @@ impl Agent { pub fn delete(&self, path: &str) -> Request { self.request("DELETE", path) } + + /// Read access to the cookie store. + /// + /// Used to persist the cookies to an external writer. + /// + /// ```no_run + /// use std::io::Write; + /// use std::fs::File; + /// + /// let mut file = File::create("cookies.json").unwrap(); + /// + /// let agent = ureq::agent(); + /// + /// // Cookies set by www.google.com are stored in agent. + /// agent.get("https://www.google.com/").call().unwrap(); + /// + /// // Saves (persistent) cookies + /// agent.cookie_store().save_json(&mut file).unwrap(); + /// ``` + #[cfg(feature = "cookies")] + pub fn cookie_store(&self) -> CookieStoreGuard<'_> { + self.state.cookie_tin.read_lock() + } } const DEFAULT_MAX_IDLE_CONNECTIONS: usize = 100; diff --git a/src/cookies.rs b/src/cookies.rs index 13982d9..80d7686 100644 --- a/src/cookies.rs +++ b/src/cookies.rs @@ -1,5 +1,8 @@ #[cfg(feature = "cookies")] -use std::sync::RwLock; +use { + std::ops::Deref, + std::sync::{RwLock, RwLockReadGuard}, +}; #[cfg(feature = "cookies")] use cookie_store::CookieStore; @@ -12,6 +15,16 @@ pub(crate) struct CookieTin { inner: RwLock, } +/// RAII guard for read access to the CookieStore. +pub struct CookieStoreGuard<'a>(RwLockReadGuard<'a, CookieStore>); + +impl<'a> Deref for CookieStoreGuard<'a> { + type Target = CookieStore; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + #[cfg(feature = "cookies")] impl CookieTin { pub(crate) fn new(store: CookieStore) -> Self { @@ -19,6 +32,12 @@ impl CookieTin { inner: RwLock::new(store), } } + + pub(crate) fn read_lock(&self) -> CookieStoreGuard<'_> { + let lock = self.inner.read().unwrap(); + CookieStoreGuard(lock) + } + pub(crate) fn get_request_cookies(&self, url: &Url) -> Vec { let store = self.inner.read().unwrap(); store