reqwest_middleware/
middleware.rs
1use reqwest::{Client, Request, Response};
2use std::sync::Arc;
3use task_local_extensions::Extensions;
4
5use crate::error::{Error, Result};
6
7#[cfg_attr(not(target_arch = "wasm32"), async_trait::async_trait)]
35#[cfg_attr(target_arch = "wasm32", async_trait::async_trait(?Send))]
36pub trait Middleware: 'static + Send + Sync {
37 async fn handle(
43 &self,
44 req: Request,
45 extensions: &mut Extensions,
46 next: Next<'_>,
47 ) -> Result<Response>;
48}
49
50#[cfg_attr(not(target_arch = "wasm32"), async_trait::async_trait)]
51#[cfg_attr(target_arch = "wasm32", async_trait::async_trait(?Send))]
52impl<F> Middleware for F
53where
54 F: Send
55 + Sync
56 + 'static
57 + for<'a> Fn(Request, &'a mut Extensions, Next<'a>) -> BoxFuture<'a, Result<Response>>,
58{
59 async fn handle(
60 &self,
61 req: Request,
62 extensions: &mut Extensions,
63 next: Next<'_>,
64 ) -> Result<Response> {
65 (self)(req, extensions, next).await
66 }
67}
68
69#[derive(Clone)]
75pub struct Next<'a> {
76 client: &'a Client,
77 middlewares: &'a [Arc<dyn Middleware>],
78}
79
80#[cfg(not(target_arch = "wasm32"))]
81pub type BoxFuture<'a, T> = std::pin::Pin<Box<dyn std::future::Future<Output = T> + Send + 'a>>;
82#[cfg(target_arch = "wasm32")]
83pub type BoxFuture<'a, T> = std::pin::Pin<Box<dyn std::future::Future<Output = T> + 'a>>;
84
85impl<'a> Next<'a> {
86 pub(crate) fn new(client: &'a Client, middlewares: &'a [Arc<dyn Middleware>]) -> Self {
87 Next {
88 client,
89 middlewares,
90 }
91 }
92
93 pub fn run(
94 mut self,
95 req: Request,
96 extensions: &'a mut Extensions,
97 ) -> BoxFuture<'a, Result<Response>> {
98 if let Some((current, rest)) = self.middlewares.split_first() {
99 self.middlewares = rest;
100 Box::pin(current.handle(req, extensions, self))
101 } else {
102 Box::pin(async move { self.client.execute(req).await.map_err(Error::from) })
103 }
104 }
105}