Commit Diff


commit - 87e1be84a219cdfabd7d13aa98d7fd66b0d05704
commit + abbece2d4cffddf1a71d31ee715695610cb7871a
blob - 01cf8463955196baf438637f59a5c99f10403f6b
blob + 2f76393a844b9b813e9f3bcf92349060066b6dff
--- web/README.md
+++ web/README.md
@@ -1,10 +1,15 @@
 # web template
 
-* Axum
-* Graceful Shutdown
-* Minijinja
-* Prometheus
-* Middleware Ip
-* Config
-* Tracing
-* 404
+* [x] Axum
+* [x] Graceful Shutdown
+* [x] Minijinja
+* [x] Prometheus
+* [ ] Middleware Ip
+* [x] Request Id Header
+* [x] Static files
+* [ ] Config
+* [x] Tracing
+* [ ] Messages (like flask)
+* [x] Sessions
+* [ ] CSRF
+* [ ] 404
blob - 4d421e1712dc62ac0ea7b179ab8e26577ac21756
blob + 63bc87a3e2c89cdd680f8aca850f0d59da2837e6
--- web/template/Cargo.toml
+++ web/template/Cargo.toml
@@ -13,8 +13,10 @@ metrics = { version = "=0.24.2", default-features = fa
 metrics-exporter-prometheus = { version = "=0.17.2", default-features = false }
 minijinja = "=2.12.0"
 serde = { version = "=1.0.228", features = ["derive"] }
+time = "=0.3.44"
 tokio = { version = "=1.48.0", features = ["macros", "rt-multi-thread", "signal"] }
 tower-http = { version = "=0.6.6", features = ["timeout", "trace", "fs", "request-id"] }
+tower-sessions = "=0.14.0"
 tracing = "=0.1.41"
 tracing-subscriber = { version = "=0.3.20", features = ["env-filter"] }
 
blob - 1e002169f79037057ca3631f69e2749b83251b4b
blob + 45112a324af8f1f02f41c7c4107e474bff1580c8
--- web/template/src/router.rs
+++ web/template/src/router.rs
@@ -13,7 +13,7 @@
 // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 //
-use std::{sync::Arc, time::Duration};
+use std::sync::Arc;
 
 use axum::{
     Router,
@@ -24,6 +24,8 @@ use axum::{
     routing::get,
 };
 use minijinja::context;
+use serde::{Deserialize, Serialize};
+use time::Duration;
 use tower_http::{
     request_id::{
         MakeRequestUuid, PropagateRequestIdLayer, SetRequestIdLayer,
@@ -32,20 +34,28 @@ use tower_http::{
     timeout::TimeoutLayer,
     trace::TraceLayer,
 };
+use tower_sessions::{Expiry, MemoryStore, Session, SessionManagerLayer};
 use tracing::{error, info_span};
 
 use crate::metric::track_metrics;
 use crate::state::AppState;
 
+const COUNTER_KEY: &str = "counter";
 const REQUEST_ID_HEADER: &str = "x-request-id";
 
+#[derive(Default, Deserialize, Serialize)]
+struct Counter(usize);
+
 pub(crate) fn route(app_state: Arc<AppState>) -> Router {
     let x_request_id = HeaderName::from_static(REQUEST_ID_HEADER);
 
+    let session_store = MemoryStore::default();
+
     Router::new()
         .route("/", get(handler_home))
         .route("/content", get(handler_content))
         .route("/about", get(handler_about))
+        .route("/session", get(handler_session))
         // TODO(msi): from config folder asssets
         .nest_service("/assets", ServeDir::new("assets"))
         .layer((
@@ -67,8 +77,11 @@ pub(crate) fn route(app_state: Arc<AppState>) -> Route
                     }
                 },
             ),
+            SessionManagerLayer::new(session_store)
+                .with_secure(false)
+                .with_expiry(Expiry::OnInactivity(Duration::seconds(10))),
             // TODO(msi): from config
-            TimeoutLayer::new(Duration::from_secs(10)),
+            TimeoutLayer::new(std::time::Duration::from_secs(10)),
             PropagateRequestIdLayer::new(x_request_id),
         ))
         .route_layer(middleware::from_fn(track_metrics))
@@ -76,6 +89,13 @@ pub(crate) fn route(app_state: Arc<AppState>) -> Route
         .with_state(app_state)
 }
 
+async fn handler_session(session: Session) -> impl IntoResponse {
+    let counter: Counter =
+        session.get(COUNTER_KEY).await.unwrap().unwrap_or_default();
+    session.insert(COUNTER_KEY, counter.0 + 1).await.unwrap();
+    format!("Current count: {}", counter.0)
+}
+
 async fn healthz() -> impl IntoResponse {
     StatusCode::OK
 }
blob - 02232bcc6116173cbbcaab69161cdd4ea05e4b02
blob + 1ee943a0a2f2c1fcc1d56825bb7277c0189a2817
--- web/template/templates/layout.jinja
+++ web/template/templates/layout.jinja
@@ -8,6 +8,7 @@
             <li><a href="/">Home</a></li>
             <li><a href="/content">Content</a></li>
             <li><a href="/about">About</a></li>
+            <li><a href="/session">Session</a></li>
         </ul>
     </nav>
     <h1><h1>Hello, World web =]</h1>