diff --git a/src/agent.rs b/src/agent.rs index 70275b7..c2fc1c9 100644 --- a/src/agent.rs +++ b/src/agent.rs @@ -43,7 +43,7 @@ pub struct AgentBuilder { #[cfg(feature = "cookies")] cookie_store: Option, resolver: ArcResolver, - middleware: Vec>, + middleware: Vec>, } /// Config as built by AgentBuilder and then static for the lifetime of the Agent. @@ -111,7 +111,7 @@ pub(crate) struct AgentState { #[cfg(feature = "cookies")] pub(crate) cookie_tin: CookieTin, pub(crate) resolver: ArcResolver, - pub(crate) middleware: Vec>, + pub(crate) middleware: Vec>, } impl Agent { @@ -602,7 +602,7 @@ impl AgentBuilder { /// All requests made by the agent will use this middleware. Middleware is invoked /// in the order they are added to the builder. pub fn middleware(mut self, m: impl Middleware + Send + Sync + 'static) -> Self { - self.middleware.push(Arc::new(m)); + self.middleware.push(Box::new(m)); self } } diff --git a/src/middleware.rs b/src/middleware.rs index 6e06d1b..ff6c2fc 100644 --- a/src/middleware.rs +++ b/src/middleware.rs @@ -1,5 +1,3 @@ -use std::sync::Arc; - use crate::{Error, Request, Response}; /// Chained processing of request (and response). @@ -135,13 +133,21 @@ pub trait Middleware { /// Continuation of a [`Middleware`] chain. pub struct MiddlewareNext<'a> { - pub(crate) chain: Box>>, + pub(crate) chain: &'a mut (dyn Iterator), + // Since request_fn consumes the Payload<'a>, we must have an FnOnce. + // + // It's possible to get rid of this Box if we make MiddlewareNext generic + // over some type variable, i.e. MiddlewareNext<'a, R> where R: FnOnce... + // however that would "leak" to Middleware::handle introducing a complicated + // type signature that is totally irrelevant for someone implementing a middleware. + // + // So in the name of having a sane external API, we accept this Box. pub(crate) request_fn: Box Result + 'a>, } impl<'a> MiddlewareNext<'a> { /// Continue the middleware chain by providing (a possibly amended) [`Request`]. - pub fn handle(mut self, request: Request) -> Result { + pub fn handle(self, request: Request) -> Result { if let Some(step) = self.chain.next() { step.handle(request, self) } else { diff --git a/src/request.rs b/src/request.rs index 9bf5418..fc506f0 100644 --- a/src/request.rs +++ b/src/request.rs @@ -7,8 +7,8 @@ use crate::body::Payload; use crate::header::{self, Header}; use crate::middleware::MiddlewareNext; use crate::unit::{self, Unit}; -use crate::Response; use crate::{agent::Agent, error::Error}; +use crate::{Middleware, Response}; pub type Result = std::result::Result; @@ -141,9 +141,13 @@ impl Request { }; let response = if !self.agent.state.middleware.is_empty() { - let middleware = self.agent.state.middleware.clone(); - - let chain = Box::new(middleware.into_iter()); + // Clone agent to get a local copy with same lifetime as Payload + let agent = self.agent.clone(); + let chain = &mut agent + .state + .middleware + .iter() + .map(|mw| mw.as_ref() as &dyn Middleware); let request_fn = Box::new(request_fn);