diff --git a/src/main.rs b/src/main.rs index 62c1257..cea7ca0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,13 +2,13 @@ use std::collections::HashMap; use std::sync::Arc; use cookie::{Cookie, SameSite}; -use futures::TryFutureExt; use log::{debug, error, info, trace}; -use sessions::{Session, SessionStatus, Storable}; +use sessions::Session; use warp::{Filter, Rejection, Reply}; use warp::http::{StatusCode, Uri}; -const SESSION_HEADER: &str = "Spectrum-Session"; +mod session; +use crate::session::{NoSession, SESSION_HEADER, SESSION_NAME, SessionPolicy, with_session}; #[tokio::main] async fn main() { @@ -78,44 +78,6 @@ where From: 'static, }) } -#[derive(Debug, Clone, Copy)] -enum SessionPolicy { - Existing, - AllowNew -} - -const SESSION_NAME: &str = "name"; - -fn with_session(store: Arc, - policy: SessionPolicy) -> impl Filter + Clone { - warp::cookie::cookie(SESSION_HEADER) - .and_then(move |session_id: String| { - trace!("Looking up session: {}", session_id); - let store = store.clone(); // pending async reqs allowed to outlive returned Filter - async move { - let session = store.get(&session_id).await?; - session.set_id(session_id)?; - Ok(session) - } - }.map_err(|err: std::io::Error| warp::reject::custom(ServerError(Box::new(err))))) - .or_else(clarify_error::<_, warp::reject::MissingCookie, NoSession>) // Has cookies, but not session cookie - .or_else(clarify_error::<_, warp::reject::InvalidHeader, NoSession>) // No cookies at all - .and_then(move |session: Session| async move { - match (session.status(), policy) { - (Ok(SessionStatus::Existed), _ ) - // Session exists, but name might not be set yet - if session.get::(SESSION_NAME) - .map_or(false, |name| name.filter(|name| !name.is_empty()).is_some()) => Ok(session), - (Ok(SessionStatus::Existed), _ ) => Err(warp::reject::custom(BadName)), - (Ok(SessionStatus::Created), SessionPolicy::AllowNew) => Ok(session), - (Ok(SessionStatus::Created), _) => Err(warp::reject::custom(NoSession)), - (Err(e), _) => Err(warp::reject::custom(ServerError(Box::new(e)))), - _ => Err(warp::reject::custom(NoSession)) - } - }) -} - #[derive(Debug, Default)] struct BadName; impl warp::reject::Reject for BadName {} @@ -135,10 +97,6 @@ async fn handle_reject(err: Rejection) -> Result, Rejection> { struct ServerError(Box); impl warp::reject::Reject for ServerError {} -#[derive(Debug, Default)] -struct NoSession; -impl warp::reject::Reject for NoSession {} - async fn handle_no_session(err: Rejection) -> Result { match err.find() { Some(NoSession) => { diff --git a/src/session.rs b/src/session.rs new file mode 100644 index 0000000..bdc6836 --- /dev/null +++ b/src/session.rs @@ -0,0 +1,51 @@ +use std::sync::Arc; + +use futures::TryFutureExt; +use log::trace; +use sessions::{Session, SessionStatus, Storable}; +use warp::{Filter, Rejection}; + +use crate::{BadName, clarify_error, ServerError}; + +pub const SESSION_HEADER: &str = "Spectrum-Session"; +pub const SESSION_NAME: &str = "name"; + +#[derive(Debug, Clone, Copy)] +pub enum SessionPolicy { + Existing, + AllowNew +} + +pub fn with_session(store: Arc, + policy: SessionPolicy) -> impl Filter + Clone { + warp::cookie::cookie(SESSION_HEADER) + .and_then(move |session_id: String| { + trace!("Looking up session: {}", session_id); + let store = store.clone(); // pending async reqs allowed to outlive returned Filter + async move { + let session = store.get(&session_id).await?; + session.set_id(session_id)?; + Ok(session) + } + }.map_err(|err: std::io::Error| warp::reject::custom(ServerError(Box::new(err))))) + .or_else(clarify_error::<_, warp::reject::MissingCookie, NoSession>) // Has cookies, but not session cookie + .or_else(clarify_error::<_, warp::reject::InvalidHeader, NoSession>) // No cookies at all + .and_then(move |session: Session| async move { + match (session.status(), policy) { + (Ok(SessionStatus::Existed), _ ) + // Session exists, but name might not be set yet + if session.get::(SESSION_NAME) + .map_or(false, |name| name.filter(|name| !name.is_empty()).is_some()) => Ok(session), + (Ok(SessionStatus::Existed), _ ) => Err(warp::reject::custom(BadName)), + (Ok(SessionStatus::Created), SessionPolicy::AllowNew) => Ok(session), + (Ok(SessionStatus::Created), _) => Err(warp::reject::custom(NoSession)), + (Err(e), _) => Err(warp::reject::custom(ServerError(Box::new(e)))), + _ => Err(warp::reject::custom(NoSession)) + } + }) +} + +#[derive(Debug, Default)] +pub struct NoSession; +impl warp::reject::Reject for NoSession {}