From 43680335dc110c869abbf48d46a8e677bd78a48b Mon Sep 17 00:00:00 2001 From: Martin Algesten Date: Mon, 20 Dec 2021 22:02:36 +0100 Subject: [PATCH] Middleware chain based on iterator --- src/middleware.rs | 25 ++++++++----------------- src/request.rs | 23 +++++++++-------------- 2 files changed, 17 insertions(+), 31 deletions(-) diff --git a/src/middleware.rs b/src/middleware.rs index 4bcdce8..6e06d1b 100644 --- a/src/middleware.rs +++ b/src/middleware.rs @@ -134,27 +134,18 @@ pub trait Middleware { } /// Continuation of a [`Middleware`] chain. -pub struct MiddlewareNext<'a>(Next<'a>); - -impl<'a> MiddlewareNext<'a> { - pub(crate) fn new(n: Next<'a>) -> Self { - MiddlewareNext(n) - } -} - -pub(crate) enum Next<'a> { - /// Chained middleware. The Box around the next MiddlewareNext is to break the recursive datatype. - Chain(Arc, Box>), - /// End of the middleware chain doing the actual request invocation. - End(Box Result + 'a>), +pub struct MiddlewareNext<'a> { + pub(crate) chain: 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(self, request: Request) -> Result { - match self.0 { - Next::Chain(mw, next) => mw.handle(request, *next), - Next::End(request_fn) => request_fn(request), + pub fn handle(mut self, request: Request) -> Result { + if let Some(step) = self.chain.next() { + step.handle(request, self) + } else { + (self.request_fn)(request) } } } diff --git a/src/request.rs b/src/request.rs index cfd9178..9bf5418 100644 --- a/src/request.rs +++ b/src/request.rs @@ -5,7 +5,7 @@ use url::{form_urlencoded, ParseError, Url}; use crate::body::Payload; use crate::header::{self, Header}; -use crate::middleware::{MiddlewareNext, Next}; +use crate::middleware::MiddlewareNext; use crate::unit::{self, Unit}; use crate::Response; use crate::{agent::Agent, error::Error}; @@ -118,8 +118,6 @@ impl Request { #[cfg(any(feature = "gzip", feature = "brotli"))] self.add_accept_encoding(); - let agent = &self.agent; - let deadline = match self.timeout.or(self.agent.config.timeout) { None => None, Some(timeout) => { @@ -142,20 +140,17 @@ impl Request { unit::connect(unit, true, reader).map_err(|e| e.url(url.clone())) }; - let response = if !agent.state.middleware.is_empty() { - // This clone is quite cheap since either we are cloning a Vec>. - let middleware = agent.state.middleware.clone(); + let response = if !self.agent.state.middleware.is_empty() { + let middleware = self.agent.state.middleware.clone(); - // The request_fn is the final target in the middleware chain doing the actual invocation. - let mut chain = MiddlewareNext::new(Next::End(Box::new(request_fn))); + let chain = Box::new(middleware.into_iter()); - // Build middleware in reverse order. - for mw in middleware.into_iter().rev() { - chain = MiddlewareNext::new(Next::Chain(mw, Box::new(chain))); - } + let request_fn = Box::new(request_fn); - // Run middleware chain - chain.handle(self)? + let next = MiddlewareNext { chain, request_fn }; + + // // Run middleware chain + next.handle(self)? } else { // Run the request_fn without any further indirection. request_fn(self)?