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