MiddlewareNext iterator without Box
Thanks @jsha for showing me the way.
This commit is contained in:
@@ -43,7 +43,7 @@ pub struct AgentBuilder {
|
||||
#[cfg(feature = "cookies")]
|
||||
cookie_store: Option<CookieStore>,
|
||||
resolver: ArcResolver,
|
||||
middleware: Vec<Arc<dyn Middleware + Send + Sync>>,
|
||||
middleware: Vec<Box<dyn Middleware + Send + Sync>>,
|
||||
}
|
||||
|
||||
/// 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<Arc<dyn Middleware + Send + Sync>>,
|
||||
pub(crate) middleware: Vec<Box<dyn Middleware + Send + Sync>>,
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<dyn Iterator<Item = Arc<dyn Middleware + Send + Sync + 'static>>>,
|
||||
pub(crate) chain: &'a mut (dyn Iterator<Item = &'a dyn Middleware>),
|
||||
// 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<dyn FnOnce(Request) -> Result<Response, Error> + 'a>,
|
||||
}
|
||||
|
||||
impl<'a> MiddlewareNext<'a> {
|
||||
/// Continue the middleware chain by providing (a possibly amended) [`Request`].
|
||||
pub fn handle(mut self, request: Request) -> Result<Response, Error> {
|
||||
pub fn handle(self, request: Request) -> Result<Response, Error> {
|
||||
if let Some(step) = self.chain.next() {
|
||||
step.handle(request, self)
|
||||
} else {
|
||||
|
||||
@@ -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<T> = std::result::Result<T, Error>;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user