pavex/blueprint/
post.rs

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