diff --git a/src/service.rs b/src/service.rs index 6039292..c62a6a2 100644 --- a/src/service.rs +++ b/src/service.rs @@ -147,8 +147,18 @@ where tracing::trace!(modified = modified, empty = empty, "session response state"); match session_cookie { - Some(cookie) if empty => { + Some(mut cookie) if empty => { tracing::debug!("removing session cookie"); + + // Path and domain must be manually set to ensure a proper removal cookie is + // constructed. + // + // See: https://docs.rs/cookie/latest/cookie/struct.CookieJar.html#method.remove + cookie.set_path(session_config.path); + if let Some(domain) = session_config.domain { + cookie.set_domain(domain); + } + cookies.remove(cookie) } diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 863aaab..006f05b 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -56,11 +56,16 @@ fn routes() -> Router { pub fn build_app( mut session_manager: SessionManagerLayer, max_age: Option, + domain: Option, ) -> Router { if let Some(max_age) = max_age { session_manager = session_manager.with_expiry(Expiry::OnInactivity(max_age)); } + if let Some(domain) = domain { + session_manager = session_manager.with_domain(domain); + } + routes().layer(session_manager) } @@ -92,7 +97,7 @@ macro_rules! route_tests { #[tokio::test] async fn no_session_set() { let req = Request::builder().uri("/").body(Body::empty()).unwrap(); - let res = $create_app(Some(Duration::hours(1))) + let res = $create_app(Some(Duration::hours(1)), None) .await .oneshot(req) .await @@ -114,7 +119,7 @@ macro_rules! route_tests { .header(header::COOKIE, session_cookie.encoded().to_string()) .body(Body::empty()) .unwrap(); - let res = $create_app(Some(Duration::hours(1))) + let res = $create_app(Some(Duration::hours(1)), None) .await .oneshot(req) .await @@ -133,7 +138,7 @@ macro_rules! route_tests { .header(header::COOKIE, session_cookie.encoded().to_string()) .body(Body::empty()) .unwrap(); - let res = $create_app(Some(Duration::hours(1))) + let res = $create_app(Some(Duration::hours(1)), None) .await .oneshot(req) .await @@ -150,7 +155,7 @@ macro_rules! route_tests { .uri("/insert") .body(Body::empty()) .unwrap(); - let res = $create_app(Some(Duration::hours(1))) + let res = $create_app(Some(Duration::hours(1)), None) .await .oneshot(req) .await @@ -173,7 +178,7 @@ macro_rules! route_tests { .uri("/insert") .body(Body::empty()) .unwrap(); - let res = $create_app(None).await.oneshot(req).await.unwrap(); + let res = $create_app(None, None).await.oneshot(req).await.unwrap(); let session_cookie = get_session_cookie(res.headers()).unwrap(); assert_eq!(session_cookie.name(), "id"); @@ -186,7 +191,7 @@ macro_rules! route_tests { #[tokio::test] async fn get_session() { - let app = $create_app(Some(Duration::hours(1))).await; + let app = $create_app(Some(Duration::hours(1)), None).await; let req = Request::builder() .uri("/insert") @@ -208,7 +213,7 @@ macro_rules! route_tests { #[tokio::test] async fn get_no_value() { - let app = $create_app(Some(Duration::hours(1))).await; + let app = $create_app(Some(Duration::hours(1)), None).await; let req = Request::builder() .uri("/get_value") @@ -221,7 +226,7 @@ macro_rules! route_tests { #[tokio::test] async fn remove_last_value() { - let app = $create_app(Some(Duration::hours(1))).await; + let app = $create_app(Some(Duration::hours(1)), None).await; let req = Request::builder() .uri("/insert") @@ -249,7 +254,7 @@ macro_rules! route_tests { #[tokio::test] async fn cycle_session_id() { - let app = $create_app(Some(Duration::hours(1))).await; + let app = $create_app(Some(Duration::hours(1)), None).await; let req = Request::builder() .uri("/insert") @@ -279,7 +284,32 @@ macro_rules! route_tests { #[tokio::test] async fn flush_session() { - let app = $create_app(Some(Duration::hours(1))).await; + let app = $create_app(Some(Duration::hours(1)), None).await; + + let req = Request::builder() + .uri("/insert") + .body(Body::empty()) + .unwrap(); + let res = app.clone().oneshot(req).await.unwrap(); + let session_cookie = get_session_cookie(res.headers()).unwrap(); + + let req = Request::builder() + .uri("/flush") + .header(header::COOKIE, session_cookie.encoded().to_string()) + .body(Body::empty()) + .unwrap(); + let res = app.oneshot(req).await.unwrap(); + + let session_cookie = get_session_cookie(res.headers()).unwrap(); + + assert_eq!(session_cookie.value(), ""); + assert_eq!(session_cookie.max_age(), Some(Duration::ZERO)); + assert_eq!(session_cookie.path(), Some("/")); + } + + #[tokio::test] + async fn flush_with_domain() { + let app = $create_app(Some(Duration::hours(1)), Some("localhost".to_string())).await; let req = Request::builder() .uri("/insert") @@ -299,6 +329,8 @@ macro_rules! route_tests { assert_eq!(session_cookie.value(), ""); assert_eq!(session_cookie.max_age(), Some(Duration::ZERO)); + assert_eq!(session_cookie.domain(), Some("localhost")); + assert_eq!(session_cookie.path(), Some("/")); } }; } diff --git a/tests/integration-tests.rs b/tests/integration-tests.rs index a2ce585..5a30d22 100644 --- a/tests/integration-tests.rs +++ b/tests/integration-tests.rs @@ -8,10 +8,10 @@ mod memory_store_tests { use crate::common::build_app; - async fn app(max_age: Option) -> Router { + async fn app(max_age: Option, domain: Option) -> Router { let session_store = MemoryStore::default(); let session_manager = SessionManagerLayer::new(session_store).with_secure(true); - build_app(session_manager, max_age) + build_app(session_manager, max_age, domain) } route_tests!(app);