Commit Diff


commit - abbece2d4cffddf1a71d31ee715695610cb7871a
commit + c7a127938cc306c8499617dab086101579e2db8f
blob - 2f76393a844b9b813e9f3bcf92349060066b6dff
blob + 3fdf1a4225655dff12de93a12c6b4d04506fead0
--- web/README.md
+++ web/README.md
@@ -9,7 +9,7 @@
 * [x] Static files
 * [ ] Config
 * [x] Tracing
-* [ ] Messages (like flask)
+* [x] Messages (like flask)
 * [x] Sessions
 * [ ] CSRF
 * [ ] 404
blob - 63bc87a3e2c89cdd680f8aca850f0d59da2837e6
blob + 007e47f70907b68b74487d36b6e17685fe1d7edf
--- web/template/Cargo.toml
+++ web/template/Cargo.toml
@@ -9,6 +9,7 @@ edition = "2024"
 [dependencies]
 anyhow = "=1.0.100"
 axum = "=0.8.6"
+axum-messages = "0.8.0"
 metrics = { version = "=0.24.2", default-features = false }
 metrics-exporter-prometheus = { version = "=0.17.2", default-features = false }
 minijinja = "=2.12.0"
blob - 45112a324af8f1f02f41c7c4107e474bff1580c8
blob + aaa8b25965e97f36a3a3fd85cba20832b7651d65
--- web/template/src/router.rs
+++ web/template/src/router.rs
@@ -20,9 +20,10 @@ use axum::{
     extract::State,
     http::{HeaderName, Request, StatusCode},
     middleware,
-    response::{Html, IntoResponse},
+    response::{Html, IntoResponse, Redirect},
     routing::get,
 };
+use axum_messages::{Messages, MessagesManagerLayer};
 use minijinja::context;
 use serde::{Deserialize, Serialize};
 use time::Duration;
@@ -56,6 +57,9 @@ pub(crate) fn route(app_state: Arc<AppState>) -> Route
         .route("/content", get(handler_content))
         .route("/about", get(handler_about))
         .route("/session", get(handler_session))
+        .route("/message", get(set_messages_handler))
+        .route("/read-messages", get(read_messages_handler))
+        .layer(MessagesManagerLayer)
         // TODO(msi): from config folder asssets
         .nest_service("/assets", ServeDir::new("assets"))
         .layer((
@@ -80,6 +84,7 @@ pub(crate) fn route(app_state: Arc<AppState>) -> Route
             SessionManagerLayer::new(session_store)
                 .with_secure(false)
                 .with_expiry(Expiry::OnInactivity(Duration::seconds(10))),
+            MessagesManagerLayer,
             // TODO(msi): from config
             TimeoutLayer::new(std::time::Duration::from_secs(10)),
             PropagateRequestIdLayer::new(x_request_id),
@@ -89,6 +94,22 @@ pub(crate) fn route(app_state: Arc<AppState>) -> Route
         .with_state(app_state)
 }
 
+async fn set_messages_handler(messages: Messages) -> impl IntoResponse {
+    messages.info("Hello, world!").debug("This is a debug message.");
+
+    Redirect::to("/read-messages")
+}
+
+async fn read_messages_handler(messages: Messages) -> impl IntoResponse {
+    let messages = messages
+        .into_iter()
+        .map(|message| format!("{}: {}", message.level, message))
+        .collect::<Vec<_>>()
+        .join(", ");
+
+    if messages.is_empty() { "No messages yet!".to_string() } else { messages }
+}
+
 async fn handler_session(session: Session) -> impl IntoResponse {
     let counter: Counter =
         session.get(COUNTER_KEY).await.unwrap().unwrap_or_default();
blob - 1ee943a0a2f2c1fcc1d56825bb7277c0189a2817
blob + 946dcdc44e8a01f3853417895e92d21f0c374b05
--- web/template/templates/layout.jinja
+++ web/template/templates/layout.jinja
@@ -9,6 +9,8 @@
             <li><a href="/content">Content</a></li>
             <li><a href="/about">About</a></li>
             <li><a href="/session">Session</a></li>
+            <li><a href="/message">Set Message</a></li>
+            <li><a href="/read-messages">Read Messages</a></li>
         </ul>
     </nav>
     <h1><h1>Hello, World web =]</h1>