mirror of
https://github.com/actix/actix-web.git
synced 2025-01-02 21:38:46 +00:00
Long lasting auto-prolonged session (#1292)
Co-authored-by: Yuki Okushi <huyuumi.dev@gmail.com>
This commit is contained in:
parent
c73c2dc12c
commit
664f9a8b2d
2 changed files with 65 additions and 0 deletions
|
@ -3,6 +3,7 @@
|
||||||
## [Unreleased] - 2020-01-xx
|
## [Unreleased] - 2020-01-xx
|
||||||
|
|
||||||
* Update the `time` dependency to 0.2.5
|
* Update the `time` dependency to 0.2.5
|
||||||
|
* [#1292](https://github.com/actix/actix-web/pull/1292) Long lasting auto-prolonged session
|
||||||
|
|
||||||
## [0.3.0] - 2019-12-20
|
## [0.3.0] - 2019-12-20
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,7 @@ struct CookieSessionInner {
|
||||||
secure: bool,
|
secure: bool,
|
||||||
http_only: bool,
|
http_only: bool,
|
||||||
max_age: Option<Duration>,
|
max_age: Option<Duration>,
|
||||||
|
expires_in: Option<Duration>,
|
||||||
same_site: Option<SameSite>,
|
same_site: Option<SameSite>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,6 +73,7 @@ impl CookieSessionInner {
|
||||||
secure: true,
|
secure: true,
|
||||||
http_only: true,
|
http_only: true,
|
||||||
max_age: None,
|
max_age: None,
|
||||||
|
expires_in: None,
|
||||||
same_site: None,
|
same_site: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -97,6 +99,10 @@ impl CookieSessionInner {
|
||||||
cookie.set_domain(domain.clone());
|
cookie.set_domain(domain.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(expires_in) = self.expires_in {
|
||||||
|
cookie.set_expires(OffsetDateTime::now() + expires_in);
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(max_age) = self.max_age {
|
if let Some(max_age) = self.max_age {
|
||||||
cookie.set_max_age(max_age);
|
cookie.set_max_age(max_age);
|
||||||
}
|
}
|
||||||
|
@ -272,6 +278,17 @@ impl CookieSession {
|
||||||
Rc::get_mut(&mut self.0).unwrap().max_age = Some(value);
|
Rc::get_mut(&mut self.0).unwrap().max_age = Some(value);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the `expires` field in the session cookie being built.
|
||||||
|
pub fn expires_in(self, seconds: i64) -> CookieSession {
|
||||||
|
self.expires_in_time(Duration::seconds(seconds))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the `expires` field in the session cookie being built.
|
||||||
|
pub fn expires_in_time(mut self, value: Duration) -> CookieSession {
|
||||||
|
Rc::get_mut(&mut self.0).unwrap().expires_in = Some(value);
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S, B: 'static> Transform<S> for CookieSession
|
impl<S, B: 'static> Transform<S> for CookieSession
|
||||||
|
@ -324,6 +341,7 @@ where
|
||||||
fn call(&mut self, mut req: ServiceRequest) -> Self::Future {
|
fn call(&mut self, mut req: ServiceRequest) -> Self::Future {
|
||||||
let inner = self.inner.clone();
|
let inner = self.inner.clone();
|
||||||
let (is_new, state) = self.inner.load(&req);
|
let (is_new, state) = self.inner.load(&req);
|
||||||
|
let prolong_expiration = self.inner.expires_in.is_some();
|
||||||
Session::set_session(state.into_iter(), &mut req);
|
Session::set_session(state.into_iter(), &mut req);
|
||||||
|
|
||||||
let fut = self.service.call(req);
|
let fut = self.service.call(req);
|
||||||
|
@ -335,6 +353,9 @@ where
|
||||||
| (SessionStatus::Renewed, Some(state)) => {
|
| (SessionStatus::Renewed, Some(state)) => {
|
||||||
res.checked_expr(|res| inner.set_cookie(res, state))
|
res.checked_expr(|res| inner.set_cookie(res, state))
|
||||||
}
|
}
|
||||||
|
(SessionStatus::Unchanged, Some(state)) if prolong_expiration => {
|
||||||
|
res.checked_expr(|res| inner.set_cookie(res, state))
|
||||||
|
}
|
||||||
(SessionStatus::Unchanged, _) =>
|
(SessionStatus::Unchanged, _) =>
|
||||||
// set a new session cookie upon first request (new client)
|
// set a new session cookie upon first request (new client)
|
||||||
{
|
{
|
||||||
|
@ -478,4 +499,47 @@ mod tests {
|
||||||
let body = test::read_response(&mut app, request).await;
|
let body = test::read_response(&mut app, request).await;
|
||||||
assert_eq!(body, Bytes::from_static(b"counter: 100"));
|
assert_eq!(body, Bytes::from_static(b"counter: 100"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn prolong_expiration() {
|
||||||
|
let mut app = test::init_service(
|
||||||
|
App::new()
|
||||||
|
.wrap(CookieSession::signed(&[0; 32]).secure(false).expires_in(60))
|
||||||
|
.service(web::resource("/").to(|ses: Session| {
|
||||||
|
async move {
|
||||||
|
let _ = ses.set("counter", 100);
|
||||||
|
"test"
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
.service(
|
||||||
|
web::resource("/test/")
|
||||||
|
.to(|| async move { "no-changes-in-session" }),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
let request = test::TestRequest::get().to_request();
|
||||||
|
let response = app.call(request).await.unwrap();
|
||||||
|
let expires_1 = response
|
||||||
|
.response()
|
||||||
|
.cookies()
|
||||||
|
.find(|c| c.name() == "actix-session")
|
||||||
|
.expect("Cookie is set")
|
||||||
|
.expires()
|
||||||
|
.expect("Expiration is set");
|
||||||
|
|
||||||
|
actix_rt::time::delay_for(std::time::Duration::from_secs(1)).await;
|
||||||
|
|
||||||
|
let request = test::TestRequest::with_uri("/test/").to_request();
|
||||||
|
let response = app.call(request).await.unwrap();
|
||||||
|
let expires_2 = response
|
||||||
|
.response()
|
||||||
|
.cookies()
|
||||||
|
.find(|c| c.name() == "actix-session")
|
||||||
|
.expect("Cookie is set")
|
||||||
|
.expires()
|
||||||
|
.expect("Expiration is set");
|
||||||
|
|
||||||
|
assert!(expires_2 - expires_1 >= Duration::seconds(1));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue