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