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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
//! Request validation built on the [`validator`] crate, integrated with
//! Axum and RFC 9457 problem responses.
//!
//! This module owns three responsibilities, each in its own file:
//!
//! * [`errors`] -- walks `validator::ValidationErrors` into a client-safe JSON
//! tree and builds the validation [`Problem`](crate::Problem).
//! * [`extractor`] -- `ValidatedJson`/`ValidatedForm`/`ValidatedQuery`/
//! `ValidatedPath` Axum extractors that combine extraction + validation and
//! map rejections to [`Problem`](crate::Problem).
//! * [`rejection`] -- maps Axum extractor rejections (`JsonRejection`,
//! `QueryRejection`, `FormRejection`, `PathRejection`) to
//! [`Problem`](crate::Problem).
//! * `upload` (feature `uploads`) -- the `UploadedFile` extractor, which
//! bounds, sanitizes and content-checks one uploaded file before a handler
//! is called.
//!
//! ## Validation is the trust boundary
//!
//! At the point a handler receives a validated request, the value has passed
//! [`validator::Validate::validate`]. The handler does not re-validate.
//!
//! **Validation must not imply authorization.** A validated request is not an
//! authorized request. Authorization is a separate, explicit step (the `auth`
//! subsystem's `Policy`).
pub use ;
pub use ;
pub use from_multipart_rejection;
pub use ;
pub use ;
/// A request body that has passed validation.
///
/// `Validated<T>` is the high-level request DX type: it combines JSON body
/// extraction, deserialization, and validation into a single Axum
/// [`axum::extract::FromRequest`] extractor. When a controller takes
/// `input: Validated<StoreLinkRequest>`, the payload is extracted and
/// validated before the handler runs -- the handler may trust that validation
/// succeeded.
///
/// `Validated<T>` delegates to [`ValidatedJson<T>`]: it extracts and
/// deserializes the JSON body, validates `T` with [`validator::Validate`], and
/// maps rejections/validation failures to RFC 9457 [`Problem`] responses
/// (`application/problem+json`).
///
/// `T` must implement [`serde::de::DeserializeOwned`] (for the JSON body) and
/// [`validator::Validate`] (for the rules). The payload is validated exactly
/// once.
///
/// Use [`Validated::into_inner`] to extract the validated value in the handler.
///
/// # Example
///
/// ```
/// use arcature::prelude::*;
///
/// // `#[request]` adds `#[derive(Validate)]`; the `Deserialize` derive stays
/// // explicit so the extractor can deserialize and validate in one step.
/// #[request]
/// #[derive(Deserialize)]
/// pub struct StoreLinkRequest {
/// #[validate(url)]
/// pub url: String,
/// #[validate(length(min = 1, max = 120))]
/// pub title: String,
/// }
///
/// // A field that may legitimately be absent is an `Option<T>`; `required`
/// // is `validator`'s rule for those, not for a `String` serde already
/// // refused to deserialize without.
/// async fn store(input: Validated<StoreLinkRequest>) -> Result<RedirectResponse> {
/// let data = input.into_inner();
/// // ... create the link from `data`, which is valid by construction ...
/// Ok(redirect().to("/links"))
/// }
/// # fn main() {}
/// ```
;
/// A marker trait implemented by types that serve as a validated request.
///
/// The `#[request]` proc-macro (in `arcature-macros`) derives `Deserialize` and
/// `Validate` on the request struct and implements this trait so tooling can
/// identify request types. A request type must implement
/// [`serde::de::DeserializeOwned`] and [`validator::Validate`].
///
/// Application code rarely names this trait directly; the `#[request]` macro
/// implements it. It is here so request types are first-class in the framework
/// vocabulary even when the macro is not used (manual `impl Request for ...`
/// after deriving `Deserialize` + `Validate`).