From e31c545df072d09de80fa30fe9b0b3e38e56b003 Mon Sep 17 00:00:00 2001 From: elcharitas Date: Sat, 28 Sep 2024 10:22:35 +0100 Subject: [PATCH] feat: support for async middleware --- crates/macros/src/common/controller.rs | 2 +- crates/shared/src/core/engine.rs | 8 ++--- crates/shared/src/core/handler.rs | 23 +-------------- crates/shared/src/server/mod.rs | 2 +- crates/shared/src/traits/middleware_trait.rs | 29 ++++++++++++++++++- .../src/middlewares/notfound_middleware.rs | 2 +- .../src/middlewares/test_middleware.rs | 2 +- 7 files changed, 37 insertions(+), 31 deletions(-) diff --git a/crates/macros/src/common/controller.rs b/crates/macros/src/common/controller.rs index fd02d9c9..016a5a88 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 ba88a709..313efc5d 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) { + pub(self) fn add_middleware(&mut self, middleware: Box) { 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 79e8131a..d55b0505 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 + Send + 'sta }) }) } - -pub fn middleware(middleware: M) -> Box { - Box::new(move |ctx: &mut NgynContext, res: &mut NgynResponse| { - middleware.handle(ctx, res); - }) -} - -pub fn with_middlewares( - middleware: Vec, - handler: Box, -) -> impl Into { - 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 9dfc0f41..c1a740d3 100644 --- a/crates/shared/src/server/mod.rs +++ b/crates/shared/src/server/mod.rs @@ -16,4 +16,4 @@ pub type NgynRequest = http::Request>; pub type NgynResponse = http::Response>; pub(crate) type Routes = Vec<(String, Option, Box)>; -pub(crate) type Middlewares = Vec>; +pub(crate) type Middlewares = Vec>; diff --git a/crates/shared/src/traits/middleware_trait.rs b/crates/shared/src/traits/middleware_trait.rs index 4e1fb3f7..865e57d6 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, @@ -36,5 +38,30 @@ use crate::{ /// ``` 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 + Send; +} + +pub(crate) trait Middleware: NgynInjectable + Sync { + fn run<'a>( + &'a self, + _cx: &'a mut NgynContext, + _res: &'a mut NgynResponse, + ) -> Pin + Send + 'a>> { + Box::pin(async move {}) + } +} + +impl Middleware for T { + fn run<'a>( + &'a self, + cx: &'a mut NgynContext, + res: &'a mut NgynResponse, + ) -> Pin + 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 03ef306a..f16ed6fe 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; } diff --git a/examples/weather_app/src/middlewares/test_middleware.rs b/examples/weather_app/src/middlewares/test_middleware.rs index 9f501289..45111e96 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"); } }