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

gengteng / axum-valid / 6586130410

20 Oct 2023 09:46AM UTC coverage: 82.548% (-6.7%) from 89.277%
6586130410

push

github

gengteng
add support for validify

214 of 214 new or added lines in 7 files covered. (100.0%)

1173 of 1421 relevant lines covered (82.55%)

12.12 hits per line

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

20.0
/src/msgpack.rs
1
//! # Support for `MsgPack<T>` and `MsgPackRaw<T>` from `axum-msgpack`
2
//!
3
//! ## Feature
4
//!
5
//! Enable the `msgpack` feature to use `Valid<MsgPack<T>>` and `Valid<MsgPackRaw<T>>`.
6
//!
7
//! ## Usage
8
//!
9
//! 1. Implement `Deserialize` and `Validate` for your data type `T`.
10
//! 2. In your handler function, use `Valid<MsgPack<T>>` or `Valid<MsgPackRaw<T>>` as some parameter's type.
11
//!
12
//! ## Example
13
//!
14
//! ```no_run
15
//! #[cfg(feature = "validator")]
16
//! mod validator_example {
17
//!     use axum::routing::post;
18
//!     use axum::Json;
19
//!     use axum::Router;
20
//!     use axum_msgpack::{MsgPack, MsgPackRaw};
21
//!     use axum_valid::Valid;
22
//!     use serde::Deserialize;
23
//!     use validator::Validate;
24
//!
25
//!     pub fn router() -> Router {
26
//!         Router::new()
27
//!             .route("/msgpack", post(handler))
28
//!             .route("/msgpackraw", post(raw_handler))
29
//!     }
30
//!     async fn handler(Valid(MsgPack(parameter)): Valid<MsgPack<Parameter>>) {
31
//!         assert!(parameter.validate().is_ok());
32
//!     }
33
//!
34
//!     async fn raw_handler(Valid(MsgPackRaw(parameter)): Valid<MsgPackRaw<Parameter>>) {
35
//!         assert!(parameter.validate().is_ok());
36
//!     }
37
//!     #[derive(Validate, Deserialize)]
38
//!     pub struct Parameter {
39
//!         #[validate(range(min = 5, max = 10))]
40
//!         pub v0: i32,
41
//!         #[validate(length(min = 1, max = 10))]
42
//!         pub v1: String,
43
//!     }
44
//! }
45
//!
46
//! #[cfg(feature = "garde")]
47
//! mod garde_example {
48
//!     use axum::routing::post;
49
//!     use axum::Router;
50
//!     use axum_msgpack::{MsgPack, MsgPackRaw};
51
//!     use axum_valid::Garde;
52
//!     use serde::Deserialize;
53
//!     use garde::Validate;
54
//!     
55
//!     pub fn router() -> Router {
56
//!         Router::new()
57
//!             .route("/msgpack", post(handler))
58
//!             .route("/msgpackraw", post(raw_handler))
59
//!     }
60
//!
61
//!     async fn handler(Garde(MsgPack(parameter)): Garde<MsgPack<Parameter>>) {
62
//!         assert!(parameter.validate(&()).is_ok());
63
//!     }
64
//!
65
//!     async fn raw_handler(Garde(MsgPackRaw(parameter)): Garde<MsgPackRaw<Parameter>>) {
66
//!         assert!(parameter.validate(&()).is_ok());
67
//!     }
68
//!     #[derive(Validate, Deserialize)]
69
//!     pub struct Parameter {
70
//!         #[garde(range(min = 5, max = 10))]
71
//!         pub v0: i32,
72
//!         #[garde(length(min = 1, max = 10))]
73
//!         pub v1: String,
74
//!     }
75
//! }
76
//!
77
//! # #[tokio::main]
78
//! # async fn main() -> anyhow::Result<()> {
79
//! #     use axum::Router;
80
//! #     let router = Router::new();
81
//! #     #[cfg(feature = "validator")]
82
//! #     let router = router.nest("/validator", validator_example::router());
83
//! #     #[cfg(feature = "garde")]
84
//! #     let router = router.nest("/garde", garde_example::router());
85
//! #     axum::Server::bind(&([0u8, 0, 0, 0], 8080).into())
86
//! #         .serve(router.into_make_service())
87
//! #         .await?;
88
//! #     Ok(())
89
//! # }
90
//! ```
91
//!
92

93
use crate::HasValidate;
94
#[cfg(feature = "validator")]
95
use crate::HasValidateArgs;
96
use axum_msgpack::{MsgPack, MsgPackRaw};
97
#[cfg(feature = "validator")]
98
use validator::ValidateArgs;
99

100
impl<T> HasValidate for MsgPack<T> {
101
    type Validate = T;
102
    fn get_validate(&self) -> &T {
9✔
103
        &self.0
×
104
    }
105
}
106

107
#[cfg(feature = "validator")]
108
impl<'v, T: ValidateArgs<'v>> HasValidateArgs<'v> for MsgPack<T> {
109
    type ValidateArgs = T;
110
    fn get_validate_args(&self) -> &Self::ValidateArgs {
3✔
111
        &self.0
×
112
    }
113
}
114

115
#[cfg(feature = "validify")]
116
impl<T: validify::Modify> crate::HasModify for MsgPack<T> {
117
    type Modify = T;
118

119
    fn get_modify(&mut self) -> &mut Self::Modify {
×
120
        &mut self.0
×
121
    }
122
}
123

124
#[cfg(feature = "validify")]
125
impl<T> crate::PayloadExtractor for MsgPack<T> {
126
    type Payload = T;
127

128
    fn get_payload(self) -> Self::Payload {
×
129
        self.0
×
130
    }
131
}
132

133
#[cfg(feature = "validify")]
134
impl<T: validify::Validify> crate::HasValidify for MsgPack<T> {
135
    type Validify = T;
136
    type PayloadExtractor = MsgPack<T::Payload>;
137
    fn from_validified(v: Self::Validify) -> Self {
×
138
        MsgPack(v)
×
139
    }
140
}
141

142
impl<T> HasValidate for MsgPackRaw<T> {
143
    type Validate = T;
144
    fn get_validate(&self) -> &T {
9✔
145
        &self.0
×
146
    }
147
}
148

149
#[cfg(feature = "validator")]
150
impl<'v, T: ValidateArgs<'v>> HasValidateArgs<'v> for MsgPackRaw<T> {
151
    type ValidateArgs = T;
152
    fn get_validate_args(&self) -> &Self::ValidateArgs {
3✔
153
        &self.0
×
154
    }
155
}
156

157
#[cfg(feature = "validify")]
158
impl<T: validify::Modify> crate::HasModify for MsgPackRaw<T> {
159
    type Modify = T;
160

161
    fn get_modify(&mut self) -> &mut Self::Modify {
×
162
        &mut self.0
×
163
    }
164
}
165

166
#[cfg(feature = "validify")]
167
impl<T> crate::PayloadExtractor for MsgPackRaw<T> {
168
    type Payload = T;
169

170
    fn get_payload(self) -> Self::Payload {
×
171
        self.0
×
172
    }
173
}
174

175
#[cfg(feature = "validify")]
176
impl<T: validify::Validify> crate::HasValidify for MsgPackRaw<T> {
177
    type Validify = T;
178
    type PayloadExtractor = MsgPackRaw<T::Payload>;
179
    fn from_validified(v: Self::Validify) -> Self {
×
180
        MsgPackRaw(v)
×
181
    }
182
}
183

184
#[cfg(test)]
185
mod tests {
186
    use crate::tests::{ValidTest, ValidTestParameter};
187
    use axum::http::StatusCode;
188
    use axum_msgpack::{MsgPack, MsgPackRaw};
189
    use reqwest::RequestBuilder;
190
    use serde::Serialize;
191

192
    impl<T: ValidTestParameter + Serialize> ValidTest for MsgPack<T> {
193
        const ERROR_STATUS_CODE: StatusCode = StatusCode::BAD_REQUEST;
194

195
        fn set_valid_request(builder: RequestBuilder) -> RequestBuilder {
196
            builder
197
                .header(reqwest::header::CONTENT_TYPE, "application/msgpack")
198
                .body(
199
                    rmp_serde::to_vec_named(T::valid())
200
                        .expect("Failed to serialize parameters to msgpack"),
201
                )
202
        }
203

204
        fn set_error_request(builder: RequestBuilder) -> RequestBuilder {
205
            // `Content-Type` not set, `MsgPack` should return `415 Unsupported Media Type`
206
            builder
207
        }
208

209
        fn set_invalid_request(builder: RequestBuilder) -> RequestBuilder {
210
            builder
211
                .header(reqwest::header::CONTENT_TYPE, "application/msgpack")
212
                .body(
213
                    rmp_serde::to_vec_named(T::invalid())
214
                        .expect("Failed to serialize parameters to msgpack"),
215
                )
216
        }
217
    }
218

219
    impl<T: ValidTestParameter + Serialize> ValidTest for MsgPackRaw<T> {
220
        const ERROR_STATUS_CODE: StatusCode = StatusCode::BAD_REQUEST;
221

222
        fn set_valid_request(builder: RequestBuilder) -> RequestBuilder {
223
            builder
224
                .header(reqwest::header::CONTENT_TYPE, "application/msgpack")
225
                .body(
226
                    rmp_serde::to_vec(T::valid())
227
                        .expect("Failed to serialize parameters to msgpack"),
228
                )
229
        }
230

231
        fn set_error_request(builder: RequestBuilder) -> RequestBuilder {
232
            // `Content-Type` not set, `MsgPack` should return `415 Unsupported Media Type`
233
            builder
234
        }
235

236
        fn set_invalid_request(builder: RequestBuilder) -> RequestBuilder {
237
            builder
238
                .header(reqwest::header::CONTENT_TYPE, "application/msgpack")
239
                .body(
240
                    rmp_serde::to_vec(T::invalid())
241
                        .expect("Failed to serialize parameters to msgpack"),
242
                )
243
        }
244
    }
245
}
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