• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

gengteng / axum-valid / 6456231901

09 Oct 2023 11:53AM UTC coverage: 89.07% (+17.9%) from 71.154%
6456231901

push

github

gengteng
refactor Rejections

25 of 25 new or added lines in 3 files covered. (100.0%)

766 of 860 relevant lines covered (89.07%)

13.46 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

83.33
/src/typed_header.rs
1
//! # Support for `TypedHeader<T>`
2
//!
3
//! ## Feature
4
//!
5
//! Enable the `typed_header` feature to use `Valid<TypedHeader<T>>`.
6
//!
7
//! ## Usage
8
//!
9
//! 1. Implement `Header` and `Validate` for your data type `T`.
10
//! 2. In your handler function, use `Valid<TypedHeader<T>>` as some parameter's type.
11
//!
12
//! ## Example
13
//!
14
//! ```no_run
15
//! #[cfg(feature = "validator")]
16
//! mod validator_example {
17
//!     use axum::headers::{Error, Header, HeaderValue};
18
//!     use axum::http::HeaderName;
19
//!     use axum::routing::post;
20
//!     use axum::{Router, TypedHeader};
21
//!     use axum_valid::Valid;
22
//!     use validator::Validate;
23
//!
24
//!     pub fn router() -> Router {
25
//!         Router::new().route("/typed_header", post(handler))
26
//!     }
27
//!
28
//!     async fn handler(Valid(TypedHeader(parameter)): Valid<TypedHeader<Parameter>>) {
29
//!         assert!(parameter.validate().is_ok());
30
//!     }
31
//!
32
//!     #[derive(Validate)]
33
//!     pub struct Parameter {
34
//!         #[validate(range(min = 5, max = 10))]
35
//!         pub v0: i32,
36
//!         #[validate(length(min = 1, max = 10))]
37
//!         pub v1: String,
38
//!     }
39
//!
40
//!     static HEADER_NAME: HeaderName = HeaderName::from_static("my-header");
41
//!
42
//!     impl Header for Parameter {
43
//!         fn name() -> &'static HeaderName {
44
//!             &HEADER_NAME
45
//!         }
46
//!
47
//!         fn decode<'i, I>(_values: &mut I) -> Result<Self, Error>
48
//!         where
49
//!             Self: Sized,
50
//!             I: Iterator<Item = &'i HeaderValue>,
51
//!         {
52
//!             todo!()
53
//!         }
54
//!
55
//!         fn encode<E: Extend<HeaderValue>>(&self, _values: &mut E) {
56
//!             todo!()
57
//!         }
58
//!     }
59
//! }
60
//!
61
//! #[cfg(feature = "garde")]
62
//! mod garde_example {
63
//!     use axum::headers::{Error, Header, HeaderValue};
64
//!     use axum::http::HeaderName;
65
//!     use axum::routing::post;
66
//!     use axum::{Router, TypedHeader};
67
//!     use axum_valid::Garde;
68
//!     use garde::Validate;
69
//!
70
//!     pub fn router() -> Router {
71
//!         Router::new().route("/typed_header", post(handler))
72
//!     }
73
//!
74
//!     async fn handler(Garde(TypedHeader(parameter)): Garde<TypedHeader<Parameter>>) {
75
//!         assert!(parameter.validate(&()).is_ok());
76
//!     }
77
//!
78
//!     #[derive(Validate)]
79
//!     pub struct Parameter {
80
//!         #[garde(range(min = 5, max = 10))]
81
//!         pub v0: i32,
82
//!         #[garde(length(min = 1, max = 10))]
83
//!         pub v1: String,
84
//!     }
85
//!
86
//!     static HEADER_NAME: HeaderName = HeaderName::from_static("my-header");
87
//!
88
//!     impl Header for Parameter {
89
//!         fn name() -> &'static HeaderName {
90
//!             &HEADER_NAME
91
//!         }
92
//!
93
//!         fn decode<'i, I>(_values: &mut I) -> Result<Self, Error>
94
//!         where
95
//!             Self: Sized,
96
//!             I: Iterator<Item = &'i HeaderValue>,
97
//!         {
98
//!             todo!()
99
//!         }
100
//!
101
//!         fn encode<E: Extend<HeaderValue>>(&self, _values: &mut E) {
102
//!             todo!()
103
//!         }
104
//!     }
105
//! }
106
//!
107
//! # #[tokio::main]
108
//! # async fn main() -> anyhow::Result<()> {
109
//! #     use axum::Router;
110
//! #     let router = Router::new();
111
//! #     #[cfg(feature = "validator")]
112
//! #     let router = router.nest("/validator", validator_example::router());
113
//! #     #[cfg(feature = "garde")]
114
//! #     let router = router.nest("/garde", garde_example::router());
115
//! #     axum::Server::bind(&([0u8, 0, 0, 0], 8080).into())
116
//! #         .serve(router.into_make_service())
117
//! #         .await?;
118
//! #     Ok(())
119
//! # }
120
//! ```
121

122
use crate::HasValidate;
123
#[cfg(feature = "validator")]
124
use crate::HasValidateArgs;
125
use axum::TypedHeader;
126
#[cfg(feature = "validator")]
127
use validator::ValidateArgs;
128

129
impl<T> HasValidate for TypedHeader<T> {
130
    type Validate = T;
131
    fn get_validate(&self) -> &T {
6✔
132
        &self.0
×
133
    }
134
}
135

136
#[cfg(feature = "validator")]
137
impl<'v, T: ValidateArgs<'v>> HasValidateArgs<'v> for TypedHeader<T> {
138
    type ValidateArgs = T;
3✔
139
    fn get_validate_args(&self) -> &Self::ValidateArgs {
6✔
140
        &self.0
3✔
141
    }
142
}
143

144
#[cfg(test)]
3✔
145
mod tests {
146
    use crate::tests::{ValidTest, ValidTestParameter};
147
    use axum::headers::{Header, HeaderMapExt};
148
    use axum::http::StatusCode;
149
    use axum::TypedHeader;
150
    use reqwest::header::HeaderMap;
151
    use reqwest::RequestBuilder;
152

153
    impl<T: ValidTestParameter + Header + Clone> ValidTest for TypedHeader<T> {
154
        const ERROR_STATUS_CODE: StatusCode = StatusCode::BAD_REQUEST;
155

156
        fn set_valid_request(builder: RequestBuilder) -> RequestBuilder {
157
            let mut headers = HeaderMap::default();
158
            headers.typed_insert(T::valid().clone());
159
            builder.headers(headers)
160
        }
161

162
        fn set_error_request(builder: RequestBuilder) -> RequestBuilder {
163
            builder
164
        }
165

166
        fn set_invalid_request(builder: RequestBuilder) -> RequestBuilder {
167
            let mut headers = HeaderMap::default();
168
            headers.typed_insert(T::invalid().clone());
169
            builder.headers(headers)
170
        }
171
    }
172
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc