move code from tap to session's from_request, add tap_mut and make tap read-only
This commit is contained in:
parent
4a2287ee46
commit
af30c552ac
87
src/lib.rs
87
src/lib.rs
@ -55,22 +55,13 @@ impl<D> SessionStore<D>
|
|||||||
#[derive(PartialEq, Hash, Clone, Debug)]
|
#[derive(PartialEq, Hash, Clone, Debug)]
|
||||||
struct SessionID(String);
|
struct SessionID(String);
|
||||||
|
|
||||||
impl<'a, 'r> FromRequest<'a, 'r> for &'a SessionID {
|
impl SessionID {
|
||||||
type Error = ();
|
fn as_str(&self) -> &str {
|
||||||
|
self.0.as_str()
|
||||||
fn from_request(request: &'a Request<'r>) -> Outcome<Self, (Status, Self::Error), ()> {
|
|
||||||
Outcome::Success(request.local_cache(|| {
|
|
||||||
if let Some(cookie) = request.cookies().get(SESSION_COOKIE) {
|
|
||||||
SessionID(cookie.value().to_string()) // FIXME avoid cloning (cow?)
|
|
||||||
} else {
|
|
||||||
SessionID(
|
|
||||||
rand::thread_rng()
|
|
||||||
.sample_iter(&rand::distributions::Alphanumeric)
|
|
||||||
.take(16)
|
|
||||||
.collect(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}))
|
|
||||||
|
fn to_string(&self) -> String {
|
||||||
|
self.0.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,9 +84,11 @@ impl<'a, 'r, D> FromRequest<'a, 'r> for Session<'a, D>
|
|||||||
type Error = ();
|
type Error = ();
|
||||||
|
|
||||||
fn from_request(request: &'a Request<'r>) -> Outcome<Self, (Status, Self::Error), ()> {
|
fn from_request(request: &'a Request<'r>) -> Outcome<Self, (Status, Self::Error), ()> {
|
||||||
|
let store : State<SessionStore<D>> = request.guard().unwrap();
|
||||||
Outcome::Success(Session {
|
Outcome::Success(Session {
|
||||||
id: request.local_cache(|| {
|
id: request.local_cache(|| {
|
||||||
if let Some(cookie) = request.cookies().get(SESSION_COOKIE) {
|
// Resolve session ID
|
||||||
|
let id = if let Some(cookie) = request.cookies().get(SESSION_COOKIE) {
|
||||||
SessionID(cookie.value().to_string())
|
SessionID(cookie.value().to_string())
|
||||||
} else {
|
} else {
|
||||||
SessionID(
|
SessionID(
|
||||||
@ -104,9 +97,34 @@ impl<'a, 'r, D> FromRequest<'a, 'r> for Session<'a, D>
|
|||||||
.take(SESSION_ID_LEN)
|
.take(SESSION_ID_LEN)
|
||||||
.collect(),
|
.collect(),
|
||||||
)
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
let new_expiration = Instant::now().add(store.lifespan);
|
||||||
|
let mut wg = store.inner.write();
|
||||||
|
match wg.get_mut(id.as_str()) {
|
||||||
|
Some(ses) => {
|
||||||
|
// Check expiration
|
||||||
|
if ses.expires <= Instant::now() {
|
||||||
|
ses.data = D::default();
|
||||||
}
|
}
|
||||||
|
// Update expiry timestamp
|
||||||
|
ses.expires = new_expiration;
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
// New session
|
||||||
|
wg.insert(
|
||||||
|
id.to_string(),
|
||||||
|
SessionInstance {
|
||||||
|
data: D::default(),
|
||||||
|
expires: new_expiration,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
id
|
||||||
}),
|
}),
|
||||||
store: request.guard().unwrap(),
|
store,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -130,42 +148,21 @@ impl<'a, D> Session<'a, D>
|
|||||||
|
|
||||||
/// Set the session object to its default state
|
/// Set the session object to its default state
|
||||||
pub fn reset(&self) {
|
pub fn reset(&self) {
|
||||||
self.tap(|m| {
|
self.tap_mut(|m| {
|
||||||
*m = D::default();
|
*m = D::default();
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Renew the session without changing any data
|
pub fn tap<T>(&self, func: impl FnOnce(&D) -> T) -> T {
|
||||||
pub fn renew(&self) {
|
let rg = self.store.inner.read();
|
||||||
self.tap(|_| ())
|
let instance = rg.get(self.id.as_str()).unwrap();
|
||||||
|
func(&instance.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Run a closure with a mutable reference to the session object.
|
pub fn tap_mut<T>(&self, func: impl FnOnce(&mut D) -> T) -> T {
|
||||||
/// The closure's return value is send to the caller.
|
|
||||||
pub fn tap<T>(&self, func: impl FnOnce(&mut D) -> T) -> T {
|
|
||||||
let mut wg = self.store.inner.write();
|
let mut wg = self.store.inner.write();
|
||||||
if let Some(instance) = wg.get_mut(&self.id.0) {
|
let instance = wg.get_mut(self.id.as_str()).unwrap();
|
||||||
// wipe session data if expired
|
|
||||||
if instance.expires <= Instant::now() {
|
|
||||||
instance.data = D::default();
|
|
||||||
}
|
|
||||||
// update expiry timestamp
|
|
||||||
instance.expires = Instant::now().add(self.store.lifespan);
|
|
||||||
|
|
||||||
func(&mut instance.data)
|
func(&mut instance.data)
|
||||||
} else {
|
|
||||||
// no object in the store yet, start fresh
|
|
||||||
let mut data = D::default();
|
|
||||||
let result = func(&mut data);
|
|
||||||
wg.insert(
|
|
||||||
self.id.0.clone(),
|
|
||||||
SessionInstance {
|
|
||||||
data,
|
|
||||||
expires: Instant::now().add(self.store.lifespan),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
result
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user