pavex/blueprint/
pre.rs

1use super::reflection::AnnotationCoordinates;
2use crate::blueprint::ErrorHandler;
3use crate::blueprint::conversions::coordinates2coordinates;
4use pavex_bp_schema::{Blueprint as BlueprintSchema, Component, Location};
5
6/// The input type for [`Blueprint::pre_process`].
7///
8/// Check out [`Blueprint::pre_process`] for more information on pre-processing middlewares
9/// in Pavex.
10///
11/// # Stability guarantees
12///
13/// Use the [`pre_process`](macro@crate::pre_process) attribute macro to create instances of `PreProcessingMiddleware`.\
14/// `PreProcessingMiddleware`'s fields are an implementation detail of Pavex's macros and should not be relied upon:
15/// newer versions of Pavex may add, remove or modify its fields.
16///
17/// [`Blueprint::pre_process`]: crate::Blueprint::pre_process
18pub struct PreProcessingMiddleware {
19    #[doc(hidden)]
20    pub coordinates: AnnotationCoordinates,
21}
22
23/// The type returned by [`Blueprint::pre_process`].
24///
25/// It allows you to further configure the behaviour of the registered pre-processing
26/// middleware.
27///
28/// [`Blueprint::pre_process`]: crate::Blueprint::pre_process
29pub struct RegisteredPreProcessingMiddleware<'a> {
30    pub(crate) blueprint: &'a mut BlueprintSchema,
31    /// The index of the registered middleware in the blueprint's `components` vector.
32    pub(crate) component_id: usize,
33}
34
35impl RegisteredPreProcessingMiddleware<'_> {
36    #[track_caller]
37    /// Register an error handler.
38    ///
39    /// If an error handler has already been registered for this middleware, it will be
40    /// overwritten.
41    ///
42    /// # Guide
43    ///
44    /// Check out the ["Error handlers"](https://pavex.dev/docs/guide/errors/error_handlers)
45    /// section of Pavex's guide for a thorough introduction to error handlers
46    /// in Pavex applications.
47    ///
48    /// # Example
49    ///
50    /// ```rust
51    /// use pavex::Blueprint;
52    /// use pavex::{error_handler, pre_process, middleware::Processing};
53    /// use pavex::request::RequestHead;
54    /// use pavex::Response;
55    /// # struct LogLevel;
56    /// # struct AuthError;
57    ///
58    /// // 👇 a fallible middleware
59    /// #[pre_process]
60    /// pub fn reject_anonymous(request_head: &RequestHead) -> Result<Processing, AuthError>
61    /// {
62    ///     // [...]
63    ///     # todo!()
64    /// }
65    ///
66    /// #[error_handler]
67    /// pub fn auth_error_handler(
68    ///     #[px(error_ref)] error: &AuthError,
69    ///     log_level: LogLevel
70    /// ) -> Response {
71    ///     // [...]
72    ///     # todo!()
73    /// }
74    ///
75    /// # fn main() {
76    /// let mut bp = Blueprint::new();
77    /// bp.pre_process(REJECT_ANONYMOUS)
78    ///     .error_handler(AUTH_ERROR_HANDLER);
79    /// # }
80    /// ```
81    pub fn error_handler(mut self, error_handler: ErrorHandler) -> Self {
82        let error_handler = pavex_bp_schema::ErrorHandler {
83            coordinates: coordinates2coordinates(error_handler.coordinates),
84            registered_at: Location::caller(),
85        };
86        self.pre_processing_middleware().error_handler = Some(error_handler);
87        self
88    }
89
90    fn pre_processing_middleware(&mut self) -> &mut pavex_bp_schema::PreProcessingMiddleware {
91        let component = &mut self.blueprint.components[self.component_id];
92        let Component::PreProcessingMiddleware(c) = component else {
93            unreachable!("The component should be a pre-processing middleware")
94        };
95        c
96    }
97}