diff --git a/actix_session/index.html b/actix_session/index.html index 50b19af12..40b90dc34 100644 --- a/actix_session/index.html +++ b/actix_session/index.html @@ -6,7 +6,7 @@ logo

Crate actix_session

logo
Expand description

Session management for Actix Web.

+

Crate actix_session

source · []
Expand description

Session management for Actix Web.

The HTTP protocol, at a first glance, is stateless: the client sends a request, the server parses its content, performs some processing and returns a response. The outcome is only influenced by the provided inputs (i.e. the request content) and whatever state the server diff --git a/actix_session/trait.SessionExt.html b/actix_session/trait.SessionExt.html index b60c46ff3..04af0214e 100644 --- a/actix_session/trait.SessionExt.html +++ b/actix_session/trait.SessionExt.html @@ -4,12 +4,12 @@

+

SessionExt

logo
pub trait SessionExt {
+    

Trait actix_session::SessionExt

source · []
pub trait SessionExt {
     fn get_session(&self) -> Session;
 }
Expand description

Extract a Session object from various actix-web types (e.g. HttpRequest, ServiceRequest, ServiceResponse).

-

Required methods

Extract a Session object.

-

Implementations on Foreign Types

Implementors

+

Required methods

Extract a Session object.

+

Implementations on Foreign Types

Implementors

\ No newline at end of file diff --git a/src/actix_session/lib.rs.html b/src/actix_session/lib.rs.html index 43bc02610..5f7a13694 100644 --- a/src/actix_session/lib.rs.html +++ b/src/actix_session/lib.rs.html @@ -591,6 +591,99 @@ 584 585 586 +587 +588 +589 +590 +591 +592 +593 +594 +595 +596 +597 +598 +599 +600 +601 +602 +603 +604 +605 +606 +607 +608 +609 +610 +611 +612 +613 +614 +615 +616 +617 +618 +619 +620 +621 +622 +623 +624 +625 +626 +627 +628 +629 +630 +631 +632 +633 +634 +635 +636 +637 +638 +639 +640 +641 +642 +643 +644 +645 +646 +647 +648 +649 +650 +651 +652 +653 +654 +655 +656 +657 +658 +659 +660 +661 +662 +663 +664 +665 +666 +667 +668 +669 +670 +671 +672 +673 +674 +675 +676 +677 +678 +679
//! Session management for Actix Web.
 //!
 //! The HTTP protocol, at a first glance, is stateless: the client sends a request, the server
@@ -786,13 +879,14 @@
                 *policy,
             )
             .await;
+            acceptance_tests::guard(store_builder.clone(), *policy).await;
         }
     }
 
     mod acceptance_tests {
         use actix_web::{
             dev::Service,
-            middleware, test,
+            guard, middleware, test,
             web::{self, get, post, resource, Bytes},
             App, HttpResponse, Result,
         };
@@ -802,7 +896,7 @@
 
         use crate::{
             middleware::SessionLength, storage::SessionStore, test_helpers::key,
-            CookieContentSecurity, Session, SessionMiddleware,
+            CookieContentSecurity, Session, SessionExt, SessionMiddleware,
         };
 
         pub(super) async fn basic_workflow<F, Store>(
@@ -901,6 +995,91 @@
             assert_eq!(cookie_2.max_age(), Some(Duration::seconds(60)));
         }
 
+        pub(super) async fn guard<F, Store>(store_builder: F, policy: CookieContentSecurity)
+        where
+            Store: SessionStore + 'static,
+            F: Fn() -> Store + Clone + Send + 'static,
+        {
+            let srv = actix_test::start(move || {
+                App::new()
+                    .wrap(
+                        SessionMiddleware::builder(store_builder(), key())
+                            .cookie_name("test-session".into())
+                            .cookie_content_security(policy)
+                            .session_length(SessionLength::Predetermined {
+                                max_session_length: Some(time::Duration::days(7)),
+                            })
+                            .build(),
+                    )
+                    .wrap(middleware::Logger::default())
+                    .service(resource("/").route(get().to(index)))
+                    .service(resource("/do_something").route(post().to(do_something)))
+                    .service(resource("/login").route(post().to(login)))
+                    .service(resource("/logout").route(post().to(logout)))
+                    .service(
+                        web::scope("/protected")
+                            .guard(guard::fn_guard(|g| {
+                                g.get_session().get::<String>("user_id").unwrap().is_some()
+                            }))
+                            .service(resource("/count").route(get().to(count))),
+                    )
+            });
+
+            // Step 1: GET without session info
+            //   - response should be a unsuccessful status
+            let req_1 = srv.get("/protected/count").send();
+            let resp_1 = req_1.await.unwrap();
+            assert!(!resp_1.status().is_success());
+
+            // Step 2: POST to login
+            //   - set-cookie actix-session will be in response  (session cookie #1)
+            //   - updates session state: {"counter": 0, "user_id": "ferris"}
+            let req_2 = srv.post("/login").send_json(&json!({"user_id": "ferris"}));
+            let resp_2 = req_2.await.unwrap();
+            let cookie_1 = resp_2
+                .cookies()
+                .unwrap()
+                .clone()
+                .into_iter()
+                .find(|c| c.name() == "test-session")
+                .unwrap();
+
+            // Step 3: POST to do_something
+            //   - adds new session state:  {"counter": 1, "user_id": "ferris" }
+            //   - set-cookie actix-session should be in response (session cookie #2)
+            //   - response should be: {"counter": 1, "user_id": None}
+            let req_3 = srv.post("/do_something").cookie(cookie_1.clone()).send();
+            let mut resp_3 = req_3.await.unwrap();
+            let result_3 = resp_3.json::<IndexResponse>().await.unwrap();
+            assert_eq!(
+                result_3,
+                IndexResponse {
+                    user_id: Some("ferris".into()),
+                    counter: 1
+                }
+            );
+            let cookie_2 = resp_3
+                .cookies()
+                .unwrap()
+                .clone()
+                .into_iter()
+                .find(|c| c.name() == "test-session")
+                .unwrap();
+
+            // Step 4: GET using a existing user id
+            //   - response should be: {"counter": 3, "user_id": "ferris"}
+            let req_4 = srv.get("/protected/count").cookie(cookie_2.clone()).send();
+            let mut resp_4 = req_4.await.unwrap();
+            let result_4 = resp_4.json::<IndexResponse>().await.unwrap();
+            assert_eq!(
+                result_4,
+                IndexResponse {
+                    user_id: Some("ferris".into()),
+                    counter: 1
+                }
+            );
+        }
+
         pub(super) async fn complex_workflow<F, Store>(
             store_builder: F,
             is_invalidation_supported: bool,
@@ -1142,6 +1321,13 @@
             Ok(HttpResponse::Ok().json(&IndexResponse { user_id, counter }))
         }
 
+        async fn count(session: Session) -> Result<HttpResponse> {
+            let user_id: Option<String> = session.get::<String>("user_id").unwrap();
+            let counter: i32 = session.get::<i32>("counter").unwrap().unwrap();
+
+            Ok(HttpResponse::Ok().json(&IndexResponse { user_id, counter }))
+        }
+
         #[derive(Deserialize)]
         struct Identity {
             user_id: String,
diff --git a/src/actix_session/session_ext.rs.html b/src/actix_session/session_ext.rs.html
index 4a2681695..1489ad3fc 100644
--- a/src/actix_session/session_ext.rs.html
+++ b/src/actix_session/session_ext.rs.html
@@ -36,8 +36,16 @@
 29
 30
 31
+32
+33
+34
+35
+36
+37
+38
 
use actix_web::{
     dev::{ServiceRequest, ServiceResponse},
+    guard::GuardContext,
     HttpMessage, HttpRequest,
 };
 
@@ -67,6 +75,12 @@
         self.request().get_session()
     }
 }
+
+impl<'a> SessionExt for GuardContext<'a> {
+    fn get_session(&self) -> Session {
+        Session::get_session(&mut *self.req_data_mut())
+    }
+}
 
\ No newline at end of file