use std::sync::{Arc, Mutex};
#[derive(Debug, Clone, Default)]
pub struct ResponseCookies {
cookies: Vec<String>,
}
impl ResponseCookies {
pub fn new() -> Self {
Self {
cookies: Vec::new(),
}
}
pub fn add(&mut self, cookie: String) {
self.cookies.push(cookie);
}
pub fn cookies(&self) -> &[String] {
&self.cookies
}
}
#[derive(Clone, Default)]
pub struct SharedResponseCookies {
inner: Arc<Mutex<ResponseCookies>>,
}
impl SharedResponseCookies {
pub fn new() -> Self {
Self {
inner: Arc::new(Mutex::new(ResponseCookies::new())),
}
}
pub fn add(&self, cookie: String) {
self.inner
.lock()
.unwrap_or_else(|e| e.into_inner())
.add(cookie);
}
pub fn take(&self) -> ResponseCookies {
std::mem::take(&mut *self.inner.lock().unwrap_or_else(|e| e.into_inner()))
}
}
#[cfg(test)]
mod tests {
use super::*;
use rstest::rstest;
#[rstest]
fn test_new_response_cookies_is_empty() {
let cookies = ResponseCookies::new();
assert!(cookies.cookies().is_empty());
}
#[rstest]
fn test_add_single_cookie() {
let mut cookies = ResponseCookies::new();
cookies.add("session=abc; Path=/".to_string());
assert_eq!(cookies.cookies().len(), 1);
assert_eq!(cookies.cookies()[0], "session=abc; Path=/");
}
#[rstest]
fn test_add_multiple_cookies() {
let mut cookies = ResponseCookies::new();
cookies.add("session=abc; Path=/".to_string());
cookies.add("csrf=xyz; SameSite=Strict".to_string());
assert_eq!(cookies.cookies().len(), 2);
assert_eq!(cookies.cookies()[0], "session=abc; Path=/");
assert_eq!(cookies.cookies()[1], "csrf=xyz; SameSite=Strict");
}
#[rstest]
fn test_default_is_empty() {
let cookies = ResponseCookies::default();
assert!(cookies.cookies().is_empty());
}
#[rstest]
fn test_shared_add_and_take() {
let jar = SharedResponseCookies::new();
jar.add("session=abc; Path=/".to_string());
jar.add("csrf=xyz; SameSite=Strict".to_string());
let cookies = jar.take();
assert_eq!(cookies.cookies().len(), 2);
assert_eq!(cookies.cookies()[0], "session=abc; Path=/");
assert_eq!(cookies.cookies()[1], "csrf=xyz; SameSite=Strict");
}
#[rstest]
fn test_shared_take_empties_jar() {
let jar = SharedResponseCookies::new();
jar.add("session=abc; Path=/".to_string());
let first_take = jar.take();
let second_take = jar.take();
assert_eq!(first_take.cookies().len(), 1);
assert!(second_take.cookies().is_empty());
}
#[rstest]
fn test_shared_clone_shares_state() {
let jar = SharedResponseCookies::new();
let jar_clone = jar.clone();
jar_clone.add("session=abc; Path=/".to_string());
let cookies = jar.take();
assert_eq!(cookies.cookies().len(), 1);
assert_eq!(cookies.cookies()[0], "session=abc; Path=/");
}
#[rstest]
fn test_shared_default_is_empty() {
let jar = SharedResponseCookies::default();
let cookies = jar.take();
assert!(cookies.cookies().is_empty());
}
}