Skip to content

Commit

Permalink
fix: lazy create session
Browse files Browse the repository at this point in the history
  • Loading branch information
tejmagar committed Jun 28, 2024
1 parent def35c9 commit 4d36632
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 45 deletions.
20 changes: 0 additions & 20 deletions src/core/request/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use std::collections::HashMap;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::time::Duration;

use tokio::sync::Mutex;

Expand All @@ -16,7 +15,6 @@ use crate::core::stream::Stream;
use crate::core::path::PathParams;
use crate::{racoon_debug, racoon_error};

use crate::core::cookie;
use crate::core::cookie::{parse_cookies_from_header, Cookies};
use crate::core::session::{Session, SessionManager};
use crate::core::shortcuts::SingleText;
Expand Down Expand Up @@ -61,26 +59,8 @@ impl Request {
let cookies = parse_cookies_from_header(&headers);
let session_id = cookies.value("sessionid");

let has_session_id = session_id.is_some();
let session = Session::from(session_manager, session_id, response_headers.clone());

// If sessionid was not present in cookie, puts additional Set-Cookie header in the
// response.
if !has_session_id {
// New generated sessionid
let session_id = session.session_id().await;

{
let mut response_headers = response_headers.lock().await;
cookie::set_cookie(
&mut response_headers,
"sessionid",
session_id,
Duration::from_secs(7 * 86400),
);
}
}

Self {
stream,
context,
Expand Down
94 changes: 69 additions & 25 deletions src/core/session/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ pub mod managers;

use std::future::Future;
use std::sync::Arc;
use std::time::Duration;

use tokio::sync::Mutex;
use uuid::Uuid;

use crate::core::headers::Headers;

use super::cookie;

pub type SessionResult<T> = Box<dyn Future<Output = T> + Send + Unpin>;

pub trait AbstractSessionManager: Sync + Send {
Expand All @@ -33,7 +36,7 @@ pub type SessionManager = Box<dyn AbstractSessionManager>;

pub struct Session {
session_manager: Arc<SessionManager>,
session_id: String,
session_id: Arc<Mutex<Option<String>>>,
response_headers: Arc<Mutex<Headers>>,
}

Expand All @@ -55,16 +58,15 @@ impl Session {
) -> Self {
let session_id_value;

// If not exists, creates new session id
if let Some(session_id) = session_id {
session_id_value = session_id.to_owned();
session_id_value = Some(session_id.to_owned());
} else {
session_id_value = Uuid::new_v4().to_string();
session_id_value = None;
}

Self {
session_manager,
session_id: session_id_value,
session_id: Arc::new(Mutex::new(session_id_value)),
response_headers: response_headers.clone(),
}
}
Expand All @@ -73,8 +75,9 @@ impl Session {
/// Session id of the client received from the cookie header `sessionid`. The request instance automatically initializes
/// with new value if the `sessionid` header is not present.
///
pub async fn session_id(&self) -> &String {
&self.session_id
pub async fn session_id(&self) -> Option<String> {
// &self.session_id_ref
todo!()
}

///
Expand All @@ -91,16 +94,41 @@ impl Session {
/// ```
///
pub async fn set<S: AsRef<str>>(&self, name: S, value: S) -> std::io::Result<()> {
match self
.session_manager
.set(&self.session_id, name.as_ref(), value.as_ref())
.await
{
Ok(()) => return Ok(()),
Err(error) => {
return Err(std::io::Error::other(error));
}
};
// If sessionid was not present in cookie, puts additional Set-Cookie header in the
// response.

let mut session_id_lock = self.session_id.lock().await;
let session_id;

if !session_id_lock.is_some() {
// Lazily creates sessionid when set method is called.
session_id = Uuid::new_v4().to_string();

let mut response_headers = self.response_headers.lock().await;
cookie::set_cookie(
&mut response_headers,
"sessionid",
&session_id,
Duration::from_secs(7 * 86400),
);

*session_id_lock = Some(session_id);
}

if let Some(session_id) = &*session_id_lock {
match self
.session_manager
.set(session_id, name.as_ref(), value.as_ref())
.await
{
Ok(()) => return Ok(()),
Err(error) => {
return Err(std::io::Error::other(error));
}
};
}

Ok(())
}

///
Expand All @@ -125,9 +153,13 @@ impl Session {
/// ```
///
pub async fn get<S: AsRef<str>>(&self, name: S) -> Option<String> {
self.session_manager
.get(&self.session_id, name.as_ref())
.await
let session_id_lock = self.session_id.lock().await;

if let Some(session_id) = &*session_id_lock {
return self.session_manager.get(session_id, name.as_ref()).await;
}

None
}

///
Expand All @@ -144,9 +176,13 @@ impl Session {
/// ```
///
pub async fn remove<S: AsRef<str>>(&self, name: S) -> std::io::Result<()> {
self.session_manager
.remove(&self.session_id, name.as_ref())
.await
let session_id_lock = self.session_id.lock().await;

if let Some(session_id) = &*session_id_lock {
return self.session_manager.remove(session_id, name.as_ref()).await;
}

Ok(())
}

///
Expand All @@ -161,8 +197,16 @@ impl Session {
"{}=;Expires=Sun, 06 Nov 1994 08:49:37 GMT; Path=/",
"sessionid"
);
response_headers.insert("Set-Cookie".to_string(), vec![expire_header_value.as_bytes().to_vec()]);
response_headers.insert(
"Set-Cookie".to_string(),
vec![expire_header_value.as_bytes().to_vec()],
);

let session_lock = self.session_id.lock().await;
if let Some(session_id) = &*session_lock {
return self.session_manager.destroy(session_id).await;
}

self.session_manager.destroy(&self.session_id).await
Ok(())
}
}

0 comments on commit 4d36632

Please sign in to comment.