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")]
|
#[cfg(feature = "cookies")]
|
||||||
cookie_store: Option<CookieStore>,
|
cookie_store: Option<CookieStore>,
|
||||||
resolver: ArcResolver,
|
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.
|
/// 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")]
|
#[cfg(feature = "cookies")]
|
||||||
pub(crate) cookie_tin: CookieTin,
|
pub(crate) cookie_tin: CookieTin,
|
||||||
pub(crate) resolver: ArcResolver,
|
pub(crate) resolver: ArcResolver,
|
||||||
pub(crate) middleware: Vec<Arc<dyn Middleware + Send + Sync>>,
|
pub(crate) middleware: Vec<Box<dyn Middleware + Send + Sync>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Agent {
|
impl Agent {
|
||||||
@@ -602,7 +602,7 @@ impl AgentBuilder {
|
|||||||
/// All requests made by the agent will use this middleware. Middleware is invoked
|
/// All requests made by the agent will use this middleware. Middleware is invoked
|
||||||
/// in the order they are added to the builder.
|
/// in the order they are added to the builder.
|
||||||
pub fn middleware(mut self, m: impl Middleware + Send + Sync + 'static) -> Self {
|
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
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use crate::{Error, Request, Response};
|
use crate::{Error, Request, Response};
|
||||||
|
|
||||||
/// Chained processing of request (and response).
|
/// Chained processing of request (and response).
|
||||||
@@ -135,13 +133,21 @@ pub trait Middleware {
|
|||||||
|
|
||||||
/// Continuation of a [`Middleware`] chain.
|
/// Continuation of a [`Middleware`] chain.
|
||||||
pub struct MiddlewareNext<'a> {
|
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>,
|
pub(crate) request_fn: Box<dyn FnOnce(Request) -> Result<Response, Error> + 'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> MiddlewareNext<'a> {
|
impl<'a> MiddlewareNext<'a> {
|
||||||
/// Continue the middleware chain by providing (a possibly amended) [`Request`].
|
/// 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() {
|
if let Some(step) = self.chain.next() {
|
||||||
step.handle(request, self)
|
step.handle(request, self)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ use crate::body::Payload;
|
|||||||
use crate::header::{self, Header};
|
use crate::header::{self, Header};
|
||||||
use crate::middleware::MiddlewareNext;
|
use crate::middleware::MiddlewareNext;
|
||||||
use crate::unit::{self, Unit};
|
use crate::unit::{self, Unit};
|
||||||
use crate::Response;
|
|
||||||
use crate::{agent::Agent, error::Error};
|
use crate::{agent::Agent, error::Error};
|
||||||
|
use crate::{Middleware, Response};
|
||||||
|
|
||||||
pub type Result<T> = std::result::Result<T, Error>;
|
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 response = if !self.agent.state.middleware.is_empty() {
|
||||||
let middleware = self.agent.state.middleware.clone();
|
// Clone agent to get a local copy with same lifetime as Payload
|
||||||
|
let agent = self.agent.clone();
|
||||||
let chain = Box::new(middleware.into_iter());
|
let chain = &mut agent
|
||||||
|
.state
|
||||||
|
.middleware
|
||||||
|
.iter()
|
||||||
|
.map(|mw| mw.as_ref() as &dyn Middleware);
|
||||||
|
|
||||||
let request_fn = Box::new(request_fn);
|
let request_fn = Box::new(request_fn);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user