From eb6d51d1b9b357395b7f87fc63ea79b084a60177 Mon Sep 17 00:00:00 2001 From: fa-sharp Date: Sun, 7 Sep 2025 15:20:43 -0400 Subject: [PATCH 1/2] fix unnecessary cookie creation when updating the session data --- src/options.rs | 2 +- src/session.rs | 8 +++++--- src/session_inner.rs | 8 ++++++++ 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/options.rs b/src/options.rs index 53204aa..78ec06c 100644 --- a/src/options.rs +++ b/src/options.rs @@ -8,7 +8,7 @@ pub struct RocketFlexSessionOptions { /// The session cookie's `HttpOnly` attribute (default: `true`) pub http_only: bool, /// The session cookie's `Max-Age` attribute, in seconds. This also determines - /// the session storage TTL, unless you specify a different `ttl` setting. (default: 14 days) + /// the session storage TTL, unless you specify a different `ttl` setting. (default: 2 weeks) pub max_age: u32, /// The session cookie's `Path` attribute (default: `"/"`) pub path: String, diff --git a/src/session.rs b/src/session.rs index ce09bd2..f0ebf6c 100644 --- a/src/session.rs +++ b/src/session.rs @@ -223,9 +223,11 @@ where return; }; - // Generate new cookie - self.cookie_jar - .add_private(create_session_cookie(id, self.options)); + // Generate new session cookie if needed + if inner.is_new() { + let session_cookie = create_session_cookie(id, self.options); + self.cookie_jar.add_private(session_cookie); + } // Notify any cookie-based storage let save_result = self.storage.save_cookie( diff --git a/src/session_inner.rs b/src/session_inner.rs index a6cf405..acaf075 100644 --- a/src/session_inner.rs +++ b/src/session_inner.rs @@ -12,6 +12,8 @@ struct ActiveSession { pending_data: Option, /// Time-to-live in seconds ttl: u32, + /// Whether this is a new session that hasn't been stored yet + new: bool, } impl ActiveSession { /// Create a new active session with a generated ID, to be saved in storage @@ -21,6 +23,7 @@ impl ActiveSession { data: new_data.clone(), pending_data: Some(new_data), ttl, + new: true, } } /// Active session that already exists in storage @@ -30,6 +33,7 @@ impl ActiveSession { data, pending_data: None, ttl, + new: false, } } } @@ -79,6 +83,10 @@ where self.current.as_ref().map(|s| s.ttl) } + pub(crate) fn is_new(&self) -> bool { + self.current.as_ref().map(|s| s.new).unwrap_or(false) + } + pub(crate) fn set_data(&mut self, new_data: T, default_ttl: u32) { match &mut self.current { Some(current) => current.pending_data = Some(new_data), From 1f2c187aaae4533c86c99cefb387c21217198033 Mon Sep 17 00:00:00 2001 From: fa-sharp Date: Sun, 7 Sep 2025 15:38:04 -0400 Subject: [PATCH 2/2] tests to prevent regression --- tests/basic.rs | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/tests/basic.rs b/tests/basic.rs index e7494a9..bb56523 100644 --- a/tests/basic.rs +++ b/tests/basic.rs @@ -118,14 +118,22 @@ fn test_set_and_get_session() { .cookies() .get_private("rocket") .expect("should have session cookie"); + let cookie_value = cookie.value().to_owned(); assert_eq!(set_response.status(), Status::Ok); - assert_eq!(cookie.value(), set_response.into_string().unwrap()); + assert_eq!(cookie_value, set_response.into_string().unwrap()); // Get session let get_response = client.get("/get_session").dispatch(); assert_eq!(get_response.status(), Status::Ok); assert_eq!(get_response.into_string().unwrap(), "User: Test User (123)"); + + // Update session + let set_response = client.post("/set_session").dispatch(); + + // Verify cookie was not changed + assert_eq!(set_response.cookies().get_private("rocket"), None); + assert_eq!(set_response.status(), Status::Ok); } #[test] @@ -152,17 +160,28 @@ fn test_hashmap_session() { .dispatch(); assert_eq!(response.status(), Status::Ok); - // Verify cookie was set + // Verify session cookie was set response .cookies() .get_private("hash_session") .expect("should have session cookie"); - // Get hash value + // Set another hash value, and verify session cookie was not changed + let response = client + .post("/set_hash_session/test_key_2/test_value") + .dispatch(); + assert_eq!(response.status(), Status::Ok); + assert_eq!(response.cookies().get_private("hash_session"), None); + + // Get hash values let response = client.get("/get_hash_session/test_key").dispatch(); assert_eq!(response.status(), Status::Ok); assert_eq!(response.into_string().unwrap(), "test_value"); + let response = client.get("/get_hash_session/test_key_2").dispatch(); + assert_eq!(response.status(), Status::Ok); + assert_eq!(response.into_string().unwrap(), "test_value"); + // Get non-existent key let response = client.get("/get_hash_session/invalid_key").dispatch(); assert_eq!(response.into_string().unwrap(), "No value");