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}