split session management into separate module
This commit is contained in:
48
src/main.rs
48
src/main.rs
@@ -2,13 +2,13 @@ use std::collections::HashMap;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use cookie::{Cookie, SameSite};
|
use cookie::{Cookie, SameSite};
|
||||||
use futures::TryFutureExt;
|
|
||||||
use log::{debug, error, info, trace};
|
use log::{debug, error, info, trace};
|
||||||
use sessions::{Session, SessionStatus, Storable};
|
use sessions::Session;
|
||||||
use warp::{Filter, Rejection, Reply};
|
use warp::{Filter, Rejection, Reply};
|
||||||
use warp::http::{StatusCode, Uri};
|
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]
|
#[tokio::main]
|
||||||
async fn 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<impl Storable>,
|
|
||||||
policy: SessionPolicy) -> impl Filter<Extract = (Session,),
|
|
||||||
Error = Rejection> + 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::<String>(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)]
|
#[derive(Debug, Default)]
|
||||||
struct BadName;
|
struct BadName;
|
||||||
impl warp::reject::Reject for BadName {}
|
impl warp::reject::Reject for BadName {}
|
||||||
@@ -135,10 +97,6 @@ async fn handle_reject(err: Rejection) -> Result<Box<dyn Reply>, Rejection> {
|
|||||||
struct ServerError(Box<dyn std::error::Error + Send + Sync>);
|
struct ServerError(Box<dyn std::error::Error + Send + Sync>);
|
||||||
impl warp::reject::Reject for ServerError {}
|
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<impl Reply, Rejection> {
|
async fn handle_no_session(err: Rejection) -> Result<impl Reply, Rejection> {
|
||||||
match err.find() {
|
match err.find() {
|
||||||
Some(NoSession) => {
|
Some(NoSession) => {
|
||||||
|
|||||||
51
src/session.rs
Normal file
51
src/session.rs
Normal file
@@ -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<impl Storable>,
|
||||||
|
policy: SessionPolicy) -> impl Filter<Extract = (Session,),
|
||||||
|
Error = Rejection> + 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::<String>(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 {}
|
||||||
Reference in New Issue
Block a user