1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-11-27 17:22:57 +01:00

Allow for session cookies to be lazily created (#39)

This commit is contained in:
LJ 2020-05-25 03:27:49 +03:00 committed by GitHub
parent a0166495ea
commit e03544cb0d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -55,6 +55,7 @@ struct CookieSessionInner {
name: String, name: String,
path: String, path: String,
domain: Option<String>, domain: Option<String>,
lazy: bool,
secure: bool, secure: bool,
http_only: bool, http_only: bool,
max_age: Option<Duration>, max_age: Option<Duration>,
@ -70,6 +71,7 @@ impl CookieSessionInner {
name: "actix-session".to_owned(), name: "actix-session".to_owned(),
path: "/".to_owned(), path: "/".to_owned(),
domain: None, domain: None,
lazy: false,
secure: true, secure: true,
http_only: true, http_only: true,
max_age: None, max_age: None,
@ -84,6 +86,11 @@ impl CookieSessionInner {
state: impl Iterator<Item = (String, String)>, state: impl Iterator<Item = (String, String)>,
) -> Result<(), Error> { ) -> Result<(), Error> {
let state: HashMap<String, String> = state.collect(); let state: HashMap<String, String> = state.collect();
if self.lazy && state.is_empty() {
return Ok(());
}
let value = let value =
serde_json::to_string(&state).map_err(CookieSessionError::Serialize)?; serde_json::to_string(&state).map_err(CookieSessionError::Serialize)?;
if value.len() > 4064 { if value.len() > 4064 {
@ -247,6 +254,15 @@ impl CookieSession {
self self
} }
/// When true, prevents adding session cookies to responses until
/// the session contains data. Default is `false`.
///
/// Useful when trying to comply with laws that require consent for setting cookies.
pub fn lazy(mut self, value: bool) -> CookieSession {
Rc::get_mut(&mut self.0).unwrap().lazy = value;
self
}
/// Sets the `secure` field in the session cookie being built. /// Sets the `secure` field in the session cookie being built.
/// ///
/// If the `secure` field is set, a cookie will only be transmitted when the /// If the `secure` field is set, a cookie will only be transmitted when the
@ -426,6 +442,37 @@ mod tests {
.any(|c| c.name() == "actix-session")); .any(|c| c.name() == "actix-session"));
} }
#[actix_rt::test]
async fn lazy_cookie() {
let mut app = test::init_service(
App::new()
.wrap(CookieSession::signed(&[0; 32]).secure(false).lazy(true))
.service(web::resource("/count").to(|ses: Session| async move {
let _ = ses.set("counter", 100);
"counting"
}))
.service(web::resource("/").to(|_ses: Session| async move {
"test"
})),
)
.await;
let request = test::TestRequest::get().to_request();
let response = app.call(request).await.unwrap();
assert!(response
.response()
.cookies()
.count() == 0);
let request = test::TestRequest::with_uri("/count").to_request();
let response = app.call(request).await.unwrap();
assert!(response
.response()
.cookies()
.any(|c| c.name() == "actix-session"));
}
#[actix_rt::test] #[actix_rt::test]
async fn cookie_session_extractor() { async fn cookie_session_extractor() {
let mut app = test::init_service( let mut app = test::init_service(