@@ -100,9 +100,9 @@ impl Middlewares {
100100 let last = iter. next ( ) ?;
101101 let mut next: NextFn = {
102102 let handler = last. clone ( ) ;
103- // Call the last middleware, ignoring its `next` argument with an empty placeholder
104- Arc :: new ( move |ctx|
105- handler ( ctx , Arc :: new ( |_| Box :: pin ( async { not_found ! ( ) } ) ) ) )
103+ // Allocate the placeholder once at compose time, not per-request
104+ let dummy : NextFn = Arc :: new ( |_| Box :: pin ( async { not_found ! ( ) } ) ) ;
105+ Arc :: new ( move |ctx| handler ( ctx , dummy . clone ( ) ) )
106106 } ;
107107
108108 for mw in iter {
@@ -133,6 +133,31 @@ impl App {
133133 ///# app.run().await
134134 ///# }
135135 /// ```
136+ ///
137+ /// # Timeouts
138+ ///
139+ /// The pipeline does not enforce per-request timeouts. If your middleware
140+ /// performs a long-running or potentially unbounded operation, check the
141+ /// [`CancellationToken`](crate::CancellationToken) injected into each
142+ /// request's extensions to avoid holding connections open indefinitely:
143+ ///
144+ /// ```no_run
145+ /// use volga::{App, CancellationToken, error::Error};
146+ ///
147+ ///# #[tokio::main]
148+ ///# async fn main() -> std::io::Result<()> {
149+ /// let mut app = App::new();
150+ ///
151+ /// app.wrap(|ctx, next| async move {
152+ /// let token = ctx.extract::<CancellationToken>()?;
153+ /// tokio::select! {
154+ /// res = next(ctx) => res,
155+ /// _ = token.cancelled() => Err(Error::server_error("request cancelled")),
156+ /// }
157+ /// });
158+ ///# app.run().await
159+ ///# }
160+ /// ```
136161 pub fn wrap < F , Fut > ( & mut self , middleware : F ) -> & mut Self
137162 where
138163 F : Fn ( HttpContext , NextFn ) -> Fut + Send + Sync + ' static ,
@@ -213,6 +238,14 @@ impl App {
213238 ///# app.run().await
214239 ///# }
215240 /// ```
241+ ///
242+ /// # Security
243+ ///
244+ /// `tap_req` grants full mutable ownership of the incoming request, including
245+ /// all headers. Security-critical values such as `Authorization` can be
246+ /// stripped or overwritten before downstream middleware and handlers observe
247+ /// them. Only register trusted closures and be mindful that registration order
248+ /// determines which code sees the original request.
216249 #[ cfg( feature = "di" ) ]
217250 pub fn tap_req < F , Args , R > ( & mut self , map : F ) -> & mut Self
218251 where
@@ -259,6 +292,14 @@ impl App {
259292 ///# app.run().await
260293 ///# }
261294 /// ```
295+ ///
296+ /// # Security
297+ ///
298+ /// `tap_req` grants full mutable ownership of the incoming request, including
299+ /// all headers. Security-critical values such as `Authorization` can be
300+ /// stripped or overwritten before downstream middleware and handlers observe
301+ /// them. Only register trusted closures and be mindful that registration order
302+ /// determines which code sees the original request.
262303 #[ cfg( not( feature = "di" ) ) ]
263304 pub fn tap_req < F , R > ( & mut self , map : F ) -> & mut Self
264305 where
@@ -469,6 +510,14 @@ impl<'a> Route<'a> {
469510 ///# app.run().await
470511 ///# }
471512 /// ```
513+ ///
514+ /// # Security
515+ ///
516+ /// `tap_req` grants full mutable ownership of the incoming request, including
517+ /// all headers. Security-critical values such as `Authorization` can be
518+ /// stripped or overwritten before downstream middleware and handlers observe
519+ /// them. Only register trusted closures and be mindful that registration order
520+ /// determines which code sees the original request.
472521 #[ cfg( feature = "di" ) ]
473522 pub fn tap_req < F , Args , R > ( self , map : F ) -> Self
474523 where
@@ -513,6 +562,14 @@ impl<'a> Route<'a> {
513562 ///# app.run().await
514563 ///# }
515564 /// ```
565+ ///
566+ /// # Security
567+ ///
568+ /// `tap_req` grants full mutable ownership of the incoming request, including
569+ /// all headers. Security-critical values such as `Authorization` can be
570+ /// stripped or overwritten before downstream middleware and handlers observe
571+ /// them. Only register trusted closures and be mindful that registration order
572+ /// determines which code sees the original request.
516573 #[ cfg( not( feature = "di" ) ) ]
517574 pub fn tap_req < F , R > ( self , map : F ) -> Self
518575 where
@@ -729,15 +786,23 @@ impl<'a> RouteGroup<'a> {
729786 ///# app.run().await
730787 ///# }
731788 /// ```
789+ ///
790+ /// # Security
791+ ///
792+ /// `tap_req` grants full mutable ownership of the incoming request, including
793+ /// all headers. Security-critical values such as `Authorization` can be
794+ /// stripped or overwritten before downstream middleware and handlers observe
795+ /// them. Only register trusted closures and be mindful that registration order
796+ /// determines which code sees the original request.
732797 #[ cfg( feature = "di" ) ]
733798 pub fn tap_req < F , Args , R > ( & mut self , map : F ) -> & mut Self
734799 where
735800 F : TapReqHandler < Args , Output = R > ,
736801 R : IntoTapResult ,
737802 Args : FromContainer + Send + ' static ,
738803 {
739- let map_err_fn = make_tap_req_fn ( map) ;
740- self . middleware . push ( map_err_fn ) ;
804+ let tap_req_fn = make_tap_req_fn ( map) ;
805+ self . middleware . push ( tap_req_fn ) ;
741806 self
742807 }
743808
@@ -776,14 +841,22 @@ impl<'a> RouteGroup<'a> {
776841 ///# app.run().await
777842 ///# }
778843 /// ```
844+ ///
845+ /// # Security
846+ ///
847+ /// `tap_req` grants full mutable ownership of the incoming request, including
848+ /// all headers. Security-critical values such as `Authorization` can be
849+ /// stripped or overwritten before downstream middleware and handlers observe
850+ /// them. Only register trusted closures and be mindful that registration order
851+ /// determines which code sees the original request.
779852 #[ cfg( not( feature = "di" ) ) ]
780853 pub fn tap_req < F , R > ( & mut self , map : F ) -> & mut Self
781854 where
782855 F : TapReqHandler < Output = R > ,
783856 R : IntoTapResult ,
784857 {
785- let map_err_fn = make_tap_req_fn ( map) ;
786- self . middleware . push ( map_err_fn ) ;
858+ let tap_req_fn = make_tap_req_fn ( map) ;
859+ self . middleware . push ( tap_req_fn ) ;
787860 self
788861 }
789862
0 commit comments