autumn_web/route.rs
1//! Route descriptor types used by macro-generated code.
2//!
3//! Each route macro ([`get`](crate::get), [`post`](crate::post), etc.)
4//! generates a companion function that returns a [`Route`]. The
5//! [`routes!`](crate::routes) macro collects these into a `Vec<Route>`
6//! for the [`AppBuilder`](crate::app::AppBuilder).
7//!
8//! Users do not construct `Route` values directly -- they use the
9//! proc macros and the `routes![]` collection macro.
10
11use axum::routing::MethodRouter;
12use http::Method;
13
14use crate::openapi::ApiDoc;
15use crate::state::AppState;
16
17/// Metadata attached to routes emitted by the `#[repository(api = ...)]` macro.
18///
19/// Lets the app builder validate, at startup, that every auto-mounted CRUD
20/// endpoint is paired with a registered
21/// [`Policy`](crate::authorization::Policy).
22#[derive(Debug, Clone, Copy)]
23pub struct RepositoryApiMeta {
24 /// Stringified resource type name (e.g., `"Post"`). Used for
25 /// log messages and to look up the registered policy via
26 /// [`std::any::TypeId`] indirectly through the generated check
27 /// function in [`Self::policy_check`].
28 pub resource_type_name: &'static str,
29
30 /// Path prefix mounted by this repository (e.g., `"/api/posts"`).
31 pub api_path: &'static str,
32
33 /// `true` when the macro form used `policy = SomePolicy`, so the
34 /// auto-generated handlers enforce a record-level check before
35 /// running. `false` when the macro form is just
36 /// `#[repository(api = "...")]` — that form is rejected in
37 /// `prod` profile builds unless
38 /// `[security] allow_unauthorized_repository_api = true`.
39 pub has_policy: bool,
40
41 /// Type-erased registry probe emitted by the macro when
42 /// `policy = ...` is set. Returns `true` if a [`Policy`](crate::authorization::Policy) is
43 /// registered on the runtime
44 /// [`PolicyRegistry`](crate::authorization::PolicyRegistry) for
45 /// the resource type. Lets the app builder fail fast at
46 /// startup when a developer wires `policy = X` on the
47 /// `#[repository]` macro but forgets to call
48 /// `.policy::<R, _>(X)` on the builder — without this check,
49 /// every protected request would 500 with "no policy
50 /// registered" instead of failing fast at boot. `None` when
51 /// the macro form omits `policy = ...`.
52 pub policy_check: Option<fn(&crate::authorization::PolicyRegistry) -> bool>,
53
54 /// Type-erased registry probe emitted by the macro when
55 /// `scope = ...` is set. Returns `true` if a [`Scope`](crate::authorization::Scope) is
56 /// registered for the resource type. Companion to
57 /// [`Self::policy_check`] for the scope-list code path: the
58 /// generated `GET /<api>` handler resolves the scope from the
59 /// registry on every request, so a missing
60 /// `.scope::<R, _>(...)` registration would 500 every list
61 /// call. The startup guard fails fast instead. `None` when
62 /// the macro form omits `scope = ...`.
63 pub scope_check: Option<fn(&crate::authorization::PolicyRegistry) -> bool>,
64}
65
66/// A single route binding an HTTP method + path to an Axum handler.
67///
68/// Created by the `__autumn_route_info_{name}()` companion functions
69/// that route macros ([`get`](crate::get), [`post`](crate::post), etc.)
70/// generate. Users don't construct this directly -- they use the
71/// attribute macros and the [`routes!`](crate::routes) macro.
72///
73/// # Examples
74///
75/// ```rust,no_run
76/// use autumn_web::prelude::*;
77///
78/// #[get("/hello")]
79/// async fn hello() -> &'static str { "hi" }
80///
81/// // `routes!` expands to a Vec<Route>:
82/// let route_vec: Vec<autumn_web::Route> = routes![hello];
83/// assert_eq!(route_vec.len(), 1);
84/// ```
85pub struct Route {
86 /// HTTP method (`GET`, `POST`, `PUT`, `DELETE`, etc.).
87 pub method: Method,
88
89 /// URL path pattern (e.g., `"/users/{id}"`).
90 pub path: &'static str,
91
92 /// Axum [`MethodRouter`] that handles requests matching this route.
93 pub handler: MethodRouter<AppState>,
94
95 /// Handler function name, used for startup logging
96 /// (e.g., `"hello"`, `"create_item"`).
97 pub name: &'static str,
98
99 /// `OpenAPI` metadata inferred from the handler's signature and any
100 /// [`#[api_doc(...)]`](crate::api_doc) overrides. Consumed by
101 /// `AppBuilder::openapi` when
102 /// generating `/v3/api-docs`.
103 pub api_doc: ApiDoc,
104
105 /// Repository auto-API metadata, populated by the
106 /// `#[repository(api = ...)]` macro. `None` for hand-written
107 /// route handlers.
108 pub repository: Option<RepositoryApiMeta>,
109}