Repository: ngyn-rs/ngyn (language: rust)

Issue:
Async middleware



Discussion / hints:

Fix patch:
diff --git a/crates/macros/src/common/controller.rs b/crates/macros/src/common/controller.rs
index fd02d9c..016a5a8 100644
--- a/crates/macros/src/common/controller.rs
+++ b/crates/macros/src/common/controller.rs
@@ -131,7 +131,7 @@ pub(crate) fn controller_macro(args: TokenStream, input: TokenStream) -> TokenSt
             quote! {
                 let mut middleware = #m::default();
                 middleware.inject(cx);
-                middleware.handle(cx, res);
+                middleware.handle(cx, res).await;
             }
         })
         .collect();
diff --git a/crates/shared/src/core/engine.rs b/crates/shared/src/core/engine.rs
index ba88a70..313efc5 100644
--- a/crates/shared/src/core/engine.rs
+++ b/crates/shared/src/core/engine.rs
@@ -6,7 +6,7 @@ use std::sync::Arc;
 use super::RouteHandler;
 use crate::{
     server::{context::AppState, Method, Middlewares, NgynContext, NgynResponse, Routes},
-    traits::{NgynController, NgynInterpreter, NgynMiddleware, NgynModule},
+    traits::{Middleware, NgynController, NgynInterpreter, NgynMiddleware, NgynModule},
 };
 
 #[derive(Default)]
@@ -48,7 +48,7 @@ impl PlatformData {
 
         // trigger global middlewares
         for middleware in &self.middlewares {
-            middleware.handle(&mut cx, &mut res);
+            middleware.run(&mut cx, &mut res).await;
         }
 
         // execute controlled route if it is handled
@@ -96,7 +96,7 @@ impl PlatformData {
     /// ### Arguments
     ///
     /// * `middleware` - The middleware to add.
-    pub(self) fn add_middleware(&mut self, middleware: Box<dyn NgynMiddleware>) {
+    pub(self) fn add_middleware(&mut self, middleware: Box<dyn Middleware>) {
         self.middlewares.push(middleware);
     }
 
@@ -272,7 +272,7 @@ mod tests {
     }
 
     impl NgynMiddleware for MockMiddleware {
-        fn handle(&self, _cx: &mut NgynContext, _res: &mut NgynResponse) {}
+        async fn handle(&self, _cx: &mut NgynContext, _res: &mut NgynResponse) {}
     }
 
     struct MockInterpreter;
diff --git a/crates/shared/src/core/handler.rs b/crates/shared/src/core/handler.rs
index 79e8131..d55b050 100644
--- a/crates/shared/src/core/handler.rs
+++ b/crates/shared/src/core/handler.rs
@@ -1,9 +1,6 @@
 use std::{future::Future, pin::Pin};
 
-use crate::{
-    server::{NgynContext, NgynResponse, ToBytes},
-    traits::NgynMiddleware,
-};
+use crate::server::{NgynContext, NgynResponse, ToBytes};
 
 /// Represents a handler function that takes in a mutable reference to `NgynContext` and `NgynResponse`.
 pub type Handler = dyn Fn(&mut NgynContext, &mut NgynResponse) + Send + Sync + 'static;
@@ -76,21 +73,3 @@ pub fn async_handler<S: ToBytes + 'static, Fut: Future<Output = S> + Send + 'sta
         })
     })
 }
-
-pub fn middleware<M: NgynMiddleware + 'static>(middleware: M) -> Box<Handler> {
-    Box::new(move |ctx: &mut NgynContext, res: &mut NgynResponse| {
-        middleware.handle(ctx, res);
-    })
-}
-
-pub fn with_middlewares<M: NgynMiddleware + 'static>(
-    middleware: Vec<M>,
-    handler: Box<Handler>,
-) -> impl Into<RouteHandler> {
-    Box::new(move |ctx: &mut NgynContext, res: &mut NgynResponse| {
-        for m in &middleware {
-            m.handle(ctx, res);
-        }
-        handler(ctx, res);
-    })
-}
diff --git a/crates/shared/src/server/mod.rs b/crates/shared/src/server/mod.rs
index 9dfc0f4..c1a740d 100644
--- a/crates/shared/src/server/mod.rs
+++ b/crates/shared/src/server/mod.rs
@@ -16,4 +16,4 @@ pub type NgynRequest = http::Request<Vec<u8>>;
 pub type NgynResponse = http::Response<Full<Bytes>>;
 
 pub(crate) type Routes = Vec<(String, Option<Method>, Box<crate::core::RouteHandler>)>;
-pub(crate) type Middlewares = Vec<Box<dyn crate::traits::NgynMiddleware>>;
+pub(crate) type Middlewares = Vec<Box<dyn crate::traits::Middleware>>;
diff --git a/crates/shared/src/traits/controller_trait.rs b/crates/shared/src/traits/controller_trait.rs
index e38fbdd..9bfeb63 100644
--- a/crates/shared/src/traits/controller_trait.rs
+++ b/crates/shared/src/traits/controller_trait.rs
@@ -75,7 +75,7 @@ pub trait NgynController: NgynInjectable + Sync + Send {
 /// +-----------------+        +-----------------+        +-----------------+
 /// | Box<Ctrl>       |        | Box<Ctrl>       |        | Box<Ctrl>       |
 /// +-----------------+        +-----------------+        +-----------------+
-/// 
+///
 /// ```
 ///
 ///
diff --git a/crates/shared/src/traits/middleware_trait.rs b/crates/shared/src/traits/middleware_trait.rs
index 4e1fb3f..bc5ea54 100644
--- a/crates/shared/src/traits/middleware_trait.rs
+++ b/crates/shared/src/traits/middleware_trait.rs
@@ -1,3 +1,5 @@
+use std::{future::Future, pin::Pin};
+
 use crate::{
     server::{NgynContext, NgynResponse},
     traits::NgynInjectable,
@@ -29,12 +31,37 @@ use crate::{
 /// }
 ///
 /// impl NgynMiddleware for RequestReceivedLogger {
-///   fn handle(&self, cx: &mut NgynContext, res: &mut NgynResponse) {
+///   async fn handle(&self, cx: &mut NgynContext, res: &mut NgynResponse) {
 ///    println!("Request received: {:?}", cx.request());
 ///  }
 /// }
 /// ```
 pub trait NgynMiddleware: NgynInjectable + Sync {
     /// Handles the request.
-    fn handle(&self, cx: &mut NgynContext, res: &mut NgynResponse);
+    #[allow(async_fn_in_trait)]
+    fn handle(
+        &self,
+        cx: &mut NgynContext,
+        res: &mut NgynResponse,
+    ) -> impl std::future::Future<Output = ()> + Send;
+}
+
+pub(crate) trait Middleware: NgynInjectable + Sync {
+    fn run<'a>(
+        &'a self,
+        _cx: &'a mut NgynContext,
+        _res: &'a mut NgynResponse,
+    ) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
+        Box::pin(async move {})
+    }
+}
+
+impl<T: NgynMiddleware> Middleware for T {
+    fn run<'a>(
+        &'a self,
+        cx: &'a mut NgynContext,
+        res: &'a mut NgynResponse,
+    ) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
+        Box::pin(self.handle(cx, res))
+    }
 }
diff --git a/examples/weather_app/src/middlewares/notfound_middleware.rs b/examples/weather_app/src/middlewares/notfound_middleware.rs
index 03ef306..f16ed6f 100644
--- a/examples/weather_app/src/middlewares/notfound_middleware.rs
+++ b/examples/weather_app/src/middlewares/notfound_middleware.rs
@@ -5,7 +5,7 @@ use serde_json::json;
 pub struct NotFoundMiddleware;
 
 impl NgynMiddleware for NotFoundMiddleware {
-    fn handle(&self, cx: &mut NgynContext, res: &mut NgynResponse) {
+    async fn handle(&self, cx: &mut NgynContext, res: &mut NgynResponse) {
         if cx.is_valid_route() {
             return;
         }


Test patch:
diff --git a/examples/weather_app/src/middlewares/test_middleware.rs b/examples/weather_app/src/middlewares/test_middleware.rs
index 9f50128..45111e9 100644
--- a/examples/weather_app/src/middlewares/test_middleware.rs
+++ b/examples/weather_app/src/middlewares/test_middleware.rs
@@ -4,7 +4,7 @@ use ngyn::prelude::*;
 pub struct TestMiddleware;
 
 impl NgynMiddleware for TestMiddleware {
-    fn handle(&self, _cx: &mut NgynContext, _response: &mut NgynResponse) {
+    async fn handle(&self, _cx: &mut NgynContext, _response: &mut NgynResponse) {
         println!("middleware works");
     }
 }