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}