pavex/
middleware.rs

1//! Middleware types and utilities.
2//!
3//! # Guide
4//!
5//! Check out the ["Middleware"](https://pavex.dev/docs/guide/middleware)
6//! section of Pavex's guide for a thorough introduction to middlewares
7//! in Pavex applications.
8use std::future::IntoFuture;
9
10use crate::{IntoResponse, Response};
11
12/// A handle to trigger the execution of the rest of the request processing pipeline.
13///
14/// It is used by wrapping middlewares to delegate the processing of the request to the next
15/// middleware in the pipeline (or to the request handler).
16///
17/// Check out [`Blueprint::wrap`] for more information.
18///
19/// [`Blueprint::wrap`]: crate::Blueprint::wrap
20pub struct Next<C>
21where
22    C: IntoFuture<Output = Response>,
23{
24    request_pipeline: C,
25}
26
27/// The return type of a pre-processing middleware.
28///
29/// It signals to Pavex whether the request processing should continue or be aborted,
30/// and if so, with what response.
31///
32/// Check out [`Blueprint::pre_process`] for more information.
33///
34/// [`Blueprint::pre_process`]: crate::Blueprint::pre_process
35pub enum Processing<T = Response>
36where
37    T: IntoResponse,
38{
39    Continue,
40    EarlyReturn(T),
41}
42
43impl<T: IntoResponse> Processing<T> {
44    /// Converts the [`Processing`] instance into a response, if the intention is to abort.
45    /// It returns `None` if the intention is to continue the request processing.
46    pub fn into_response(self) -> Option<T> {
47        match self {
48            Processing::Continue => None,
49            Processing::EarlyReturn(response) => Some(response),
50        }
51    }
52}
53
54/// A wrapping middleware that...does nothing.
55///
56/// It just invokes the next stage in the request processing pipeline and returns its result.
57#[doc(hidden)]
58pub async fn wrap_noop<C: IntoFuture<Output = Response>>(next: Next<C>) -> Response {
59    next.await
60}
61
62impl<C> Next<C>
63where
64    C: IntoFuture<Output = Response>,
65{
66    /// Creates a new [`Next`] instance.
67    pub fn new(request_pipeline: C) -> Self {
68        Self { request_pipeline }
69    }
70}
71
72impl<C> IntoFuture for Next<C>
73where
74    C: IntoFuture<Output = Response>,
75{
76    type Output = Response;
77    type IntoFuture = <C as IntoFuture>::IntoFuture;
78
79    fn into_future(self) -> Self::IntoFuture {
80        self.request_pipeline.into_future()
81    }
82}