• 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

88.61
/src/validify/test.rs
1
#![cfg(feature = "validify")]
2

3
use crate::tests::{ValidTest, ValidTestParameter};
4
use crate::{
5
    HasValidate, Modified, Validated, Validified, ValidifiedByRef, VALIDATION_ERROR_STATUS,
6
};
7
use axum::extract::{Path, Query};
8
use axum::routing::{get, post};
9
use axum::{Form, Json, Router};
10
use hyper::Method;
11
use once_cell::sync::Lazy;
12
use reqwest::{StatusCode, Url};
13
use serde::{Deserialize, Serialize};
14
use std::any::type_name;
15
use std::net::SocketAddr;
16
use std::ops::Deref;
17
use validify::{Modify, Validate, Validify};
18

19
#[derive(Clone, Deserialize, Serialize, Validify, Eq, PartialEq)]
20
#[cfg_attr(feature = "extra_protobuf", derive(prost::Message))]
21
#[cfg_attr(
22
    feature = "typed_multipart",
23
    derive(axum_typed_multipart::TryFromMultipart)
24
)]
25
pub struct ParametersValidify {
26
    #[validate(range(min = 5.0, max = 10.0))]
27
    #[cfg_attr(feature = "extra_protobuf", prost(int32, tag = "1"))]
28
    v0: i32,
29
    #[modify(lowercase)]
30
    #[validate(length(min = 1, max = 10))]
31
    #[cfg_attr(feature = "extra_protobuf", prost(string, tag = "2"))]
32
    v1: String,
33
}
34

35
trait IsModified: Modify + Clone + PartialEq + Eq {
36
    fn modified(&self) -> bool {
9✔
37
        let mut cloned = self.clone();
9✔
38
        cloned.modify();
9✔
39
        cloned == *self
9✔
40
    }
41
}
42

43
impl<T> IsModified for T where T: Modify + Clone + PartialEq + Eq {}
44

45
static VALID_PARAMETERS: Lazy<ParametersValidify> = Lazy::new(|| ParametersValidify {
6✔
46
    v0: 5,
47
    v1: String::from("ABCDEFG"),
3✔
48
});
49

50
static INVALID_PARAMETERS: Lazy<ParametersValidify> = Lazy::new(|| ParametersValidify {
6✔
51
    v0: 6,
52
    v1: String::from("ABCDEFGHIJKLMN"),
3✔
53
});
54

55
impl ValidTestParameter for ParametersValidify {
56
    fn valid() -> &'static Self {
3✔
57
        VALID_PARAMETERS.deref()
3✔
58
    }
59

60
    fn error() -> &'static [(&'static str, &'static str)] {
61
        &[("not_v0_or_v1", "value")]
62
    }
63

64
    fn invalid() -> &'static Self {
3✔
65
        INVALID_PARAMETERS.deref()
3✔
66
    }
67
}
68

69
impl HasValidate for ParametersValidify {
70
    type Validate = ParametersValidify;
71

72
    fn get_validate(&self) -> &Self::Validate {
3✔
73
        self
74
    }
75
}
76

77
#[tokio::test]
18✔
78
async fn test_main() -> anyhow::Result<()> {
9✔
79
    let router = Router::new()
51✔
80
        .route(route::PATH, get(extract_path))
6✔
81
        .route(route::PATH_MODIFIED, get(extract_path_modified))
6✔
82
        .route(route::PATH_VALIDIFIED, get(extract_path_validified))
6✔
83
        .route(
84
            route::PATH_VALIDIFIED_BY_REF,
85
            get(extract_path_validified_by_ref),
3✔
86
        )
87
        .route(route::QUERY, get(extract_query))
6✔
88
        .route(route::QUERY_MODIFIED, get(extract_query_modified))
6✔
89
        .route(route::QUERY_VALIDIFIED, get(extract_query_validified))
6✔
90
        .route(
91
            route::QUERY_VALIDIFIED_BY_REF,
92
            get(extract_query_validified_by_ref),
3✔
93
        )
94
        .route(route::FORM, post(extract_form))
6✔
95
        .route(route::FORM_MODIFIED, post(extract_form_modified))
6✔
96
        .route(route::FORM_VALIDIFIED, post(extract_form_validified))
6✔
97
        .route(
98
            route::FORM_VALIDIFIED_BY_REF,
99
            post(extract_form_validified_by_ref),
3✔
100
        )
101
        .route(route::JSON, post(extract_json))
6✔
102
        .route(route::JSON_MODIFIED, post(extract_json_modified))
6✔
103
        .route(route::JSON_VALIDIFIED, post(extract_json_validified))
6✔
104
        .route(
105
            route::JSON_VALIDIFIED_BY_REF,
106
            post(extract_json_validified_by_ref),
3✔
107
        );
108

109
    #[cfg(feature = "typed_header")]
110
    let router = router.route(
6✔
111
        typed_header::route::TYPED_HEADER,
112
        post(typed_header::extract_typed_header),
3✔
113
    );
114

115
    #[cfg(feature = "typed_multipart")]
116
    let router = router
9✔
117
        .route(
118
            typed_multipart::route::TYPED_MULTIPART,
119
            post(typed_multipart::extract_typed_multipart),
3✔
120
        )
121
        .route(
122
            typed_multipart::route::BASE_MULTIPART,
123
            post(typed_multipart::extract_base_multipart),
3✔
124
        );
125

126
    #[cfg(feature = "extra")]
127
    let router = router
12✔
128
        .route(extra::route::CACHED, post(extra::extract_cached))
6✔
129
        .route(
130
            extra::route::WITH_REJECTION,
131
            post(extra::extract_with_rejection),
3✔
132
        )
133
        .route(
134
            extra::route::WITH_REJECTION_VALIDIFY,
135
            post(extra::extract_with_rejection_valid),
3✔
136
        );
137

138
    #[cfg(feature = "extra_typed_path")]
139
    let router = router
12✔
140
        .route(
141
            extra_typed_path::route::EXTRA_TYPED_PATH,
142
            get(extra_typed_path::extract_extra_typed_path),
3✔
143
        )
144
        .route(
145
            extra_typed_path::route::EXTRA_TYPED_PATH_MODIFIED,
146
            get(extra_typed_path::extract_extra_typed_path_modified),
3✔
147
        )
148
        .route(
149
            extra_typed_path::route::EXTRA_TYPED_PATH_VALIDIFIED_BY_REF,
150
            get(extra_typed_path::extract_extra_typed_path_validified_by_ref),
3✔
151
        );
152

153
    #[cfg(feature = "extra_query")]
154
    let router = router.route(
6✔
155
        extra_query::route::EXTRA_QUERY,
156
        post(extra_query::extract_extra_query),
3✔
157
    );
158

159
    #[cfg(feature = "extra_form")]
160
    let router = router.route(
6✔
161
        extra_form::route::EXTRA_FORM,
162
        post(extra_form::extract_extra_form),
3✔
163
    );
164

165
    #[cfg(feature = "extra_protobuf")]
166
    let router = router
12✔
167
        .route(
168
            extra_protobuf::route::EXTRA_PROTOBUF,
169
            post(extra_protobuf::extract_extra_protobuf),
3✔
170
        )
171
        .route(
172
            extra_protobuf::route::EXTRA_PROTOBUF_MODIFIED,
173
            post(extra_protobuf::extract_extra_protobuf_modified),
3✔
174
        )
175
        .route(
176
            extra_protobuf::route::EXTRA_PROTOBUF_VALIDIFIED_BY_REF,
177
            post(extra_protobuf::extract_extra_protobuf_validified_by_ref),
3✔
178
        );
179

180
    #[cfg(feature = "yaml")]
181
    let router = router.route(yaml::route::YAML, post(yaml::extract_yaml));
3✔
182

183
    #[cfg(feature = "msgpack")]
184
    let router = router
9✔
185
        .route(msgpack::route::MSGPACK, post(msgpack::extract_msgpack))
6✔
186
        .route(
187
            msgpack::route::MSGPACK_RAW,
188
            post(msgpack::extract_msgpack_raw),
3✔
189
        );
190

191
    let server = axum::Server::bind(&SocketAddr::from(([0u8, 0, 0, 0], 0u16)))
9✔
192
        .serve(router.into_make_service());
6✔
193
    let server_addr = server.local_addr();
3✔
194
    println!("Axum server address: {}.", server_addr);
6✔
195

196
    let (server_guard, close) = tokio::sync::oneshot::channel::<()>();
3✔
197
    let server_handle = tokio::spawn(server.with_graceful_shutdown(async move {
15✔
198
        let _ = close.await;
9✔
199
    }));
200

201
    let server_url = format!("http://{}", server_addr);
6✔
202
    let test_executor = TestExecutor::from(Url::parse(&format!("http://{}", server_addr))?);
6✔
203

204
    async fn test_extra_path(
3✔
205
        test_executor: &TestExecutor,
206
        route: &str,
207
        server_url: &str,
208
    ) -> anyhow::Result<()> {
209
        do_test_extra_path(
210
            test_executor,
211
            route,
212
            server_url,
213
            StatusCode::OK,
214
            StatusCode::BAD_REQUEST,
215
            VALIDATION_ERROR_STATUS,
216
            true,
217
        )
218
        .await
9✔
219
    }
220

221
    async fn test_extra_path_modified(
3✔
222
        test_executor: &TestExecutor,
223
        route: &str,
224
        server_url: &str,
225
    ) -> anyhow::Result<()> {
226
        do_test_extra_path(
227
            test_executor,
228
            route,
229
            server_url,
230
            StatusCode::OK,
231
            StatusCode::BAD_REQUEST,
232
            StatusCode::OK,
233
            false,
234
        )
235
        .await
9✔
236
    }
237

238
    async fn test_extra_path_validified(
3✔
239
        test_executor: &TestExecutor,
240
        route: &str,
241
        server_url: &str,
242
    ) -> anyhow::Result<()> {
243
        do_test_extra_path(
244
            test_executor,
245
            route,
246
            server_url,
247
            StatusCode::OK,
248
            StatusCode::BAD_REQUEST,
249
            VALIDATION_ERROR_STATUS,
250
            true,
251
        )
252
        .await
9✔
253
    }
254

255
    async fn do_test_extra_path(
3✔
256
        test_executor: &TestExecutor,
257
        route: &str,
258
        server_url: &str,
259
        expected_valid_status: StatusCode,
260
        expected_error_status: StatusCode,
261
        expected_invalid_status: StatusCode,
262
        should_check_json: bool,
263
    ) -> anyhow::Result<()> {
264
        let path_type_name = type_name::<Path<ParametersValidify>>();
6✔
265
        let valid_path_response = test_executor
12✔
266
            .client()
267
            .get(format!(
21✔
268
                "{}/{route}/{}/{}",
269
                server_url, VALID_PARAMETERS.v0, VALID_PARAMETERS.v1
6✔
270
            ))
271
            .send()
272
            .await?;
9✔
273
        assert_eq!(
3✔
274
            valid_path_response.status(),
6✔
275
            expected_valid_status,
276
            "Valid '{}' test failed.",
277
            path_type_name
278
        );
279

280
        let error_path_response = test_executor
12✔
281
            .client()
282
            .get(format!("{}/{route}/not_i32/path", server_url))
9✔
283
            .send()
284
            .await?;
9✔
285
        assert_eq!(
3✔
286
            error_path_response.status(),
6✔
287
            expected_error_status,
288
            "Error '{}' test failed: {}",
289
            path_type_name,
290
            error_path_response.text().await?
×
291
        );
292

293
        let invalid_path_response = test_executor
12✔
294
            .client()
295
            .get(format!(
21✔
296
                "{}/{route}/{}/{}",
297
                server_url, INVALID_PARAMETERS.v0, INVALID_PARAMETERS.v1
6✔
298
            ))
299
            .send()
300
            .await?;
9✔
301
        assert_eq!(
3✔
302
            invalid_path_response.status(),
6✔
303
            expected_invalid_status,
304
            "Invalid '{}' test failed.",
305
            path_type_name
306
        );
307
        #[cfg(feature = "into_json")]
308
        if should_check_json {
2✔
309
            check_json(path_type_name, invalid_path_response).await;
2✔
310
        }
311
        println!("All {} tests passed.", path_type_name);
6✔
312
        Ok(())
3✔
313
    }
314

315
    test_extra_path(&test_executor, "path", &server_url).await?;
6✔
316
    test_extra_path_modified(&test_executor, "path_modified", &server_url).await?;
9✔
317
    test_extra_path_validified(&test_executor, "path_validified", &server_url).await?;
9✔
318
    test_extra_path(&test_executor, "path_validified_by_ref", &server_url).await?;
9✔
319

320
    // Validated
321
    test_executor
12✔
322
        .execute::<Query<ParametersValidify>>(Method::GET, route::QUERY)
3✔
323
        .await?;
9✔
324
    // Modified
325
    test_executor
12✔
326
        .execute_modified::<Query<ParametersValidify>>(Method::GET, route::QUERY_MODIFIED)
3✔
327
        .await?;
9✔
328
    // ValidifiedByRef
329
    test_executor
12✔
330
        .execute::<Query<ParametersValidify>>(Method::GET, route::QUERY_VALIDIFIED_BY_REF)
3✔
331
        .await?;
9✔
332
    // Validified
333
    test_executor
12✔
334
        .execute_validified::<Query<ParametersValidify>>(Method::GET, route::QUERY_VALIDIFIED)
3✔
335
        .await?;
9✔
336

337
    // Validified
338
    test_executor
12✔
339
        .execute::<Form<ParametersValidify>>(Method::POST, route::FORM)
3✔
340
        .await?;
9✔
341

342
    // Validified
343
    test_executor
12✔
344
        .execute::<Json<ParametersValidify>>(Method::POST, route::JSON)
3✔
345
        .await?;
9✔
346

347
    #[cfg(feature = "typed_header")]
348
    {
349
        use axum::TypedHeader;
350
        // Validified
351
        test_executor
12✔
352
            .execute::<TypedHeader<ParametersValidify>>(
353
                Method::POST,
3✔
354
                typed_header::route::TYPED_HEADER,
355
            )
356
            .await?;
9✔
357
    }
358

359
    #[cfg(feature = "typed_multipart")]
360
    {
361
        use axum_typed_multipart::{BaseMultipart, TypedMultipart, TypedMultipartError};
362

363
        // Validified
364
        test_executor
12✔
365
            .execute::<BaseMultipart<ParametersValidify, TypedMultipartError>>(
366
                Method::POST,
3✔
367
                typed_multipart::route::BASE_MULTIPART,
368
            )
369
            .await?;
9✔
370

371
        // Validified
372
        test_executor
12✔
373
            .execute::<TypedMultipart<ParametersValidify>>(
374
                Method::POST,
3✔
375
                typed_multipart::route::TYPED_MULTIPART,
376
            )
377
            .await?;
9✔
378
    }
379

380
    #[cfg(feature = "extra")]
381
    {
382
        use axum_extra::extract::{Cached, WithRejection};
383
        use extra::{
384
            ParametersRejection, ValidifyWithRejectionRejection, WithRejectionValidifyRejection,
385
        };
386
        test_executor
12✔
387
            .execute::<Cached<ParametersValidify>>(Method::POST, extra::route::CACHED)
3✔
388
            .await?;
9✔
389
        test_executor
12✔
390
            .execute::<WithRejection<ParametersValidify, ValidifyWithRejectionRejection>>(
391
                Method::POST,
3✔
392
                extra::route::WITH_REJECTION,
393
            )
394
            .await?;
9✔
395
        test_executor
12✔
396
            .execute::<WithRejection<
397
                Validated<ParametersValidify>,
398
                WithRejectionValidifyRejection<ParametersRejection>,
399
            >>(Method::POST, extra::route::WITH_REJECTION_VALIDIFY)
3✔
400
            .await?;
9✔
401
    }
402

403
    #[cfg(feature = "extra_typed_path")]
404
    {
405
        async fn test_extra_typed_path(
3✔
406
            test_executor: &TestExecutor,
407
            route: &str,
408
            server_url: &str,
409
        ) -> anyhow::Result<()> {
410
            do_test_extra_typed_path(
411
                test_executor,
412
                route,
413
                server_url,
414
                StatusCode::OK,
415
                StatusCode::BAD_REQUEST,
416
                VALIDATION_ERROR_STATUS,
417
                true,
418
            )
419
            .await
9✔
420
        }
421

422
        async fn test_extra_typed_path_modified(
3✔
423
            test_executor: &TestExecutor,
424
            route: &str,
425
            server_url: &str,
426
        ) -> anyhow::Result<()> {
427
            do_test_extra_typed_path(
428
                test_executor,
429
                route,
430
                server_url,
431
                StatusCode::OK,
432
                StatusCode::BAD_REQUEST,
433
                StatusCode::OK,
434
                false,
435
            )
436
            .await
9✔
437
        }
438

439
        async fn do_test_extra_typed_path(
3✔
440
            test_executor: &TestExecutor,
441
            route: &str,
442
            server_url: &str,
443
            expected_valid_status: StatusCode,
444
            expected_error_status: StatusCode,
445
            expected_invalid_status: StatusCode,
446
            should_check_json: bool,
447
        ) -> anyhow::Result<()> {
448
            let extra_typed_path_type_name = "T: TypedPath";
3✔
449
            let valid_extra_typed_path_response = test_executor
12✔
450
                .client()
451
                .get(format!(
21✔
452
                    "{}/{route}/{}/{}",
453
                    server_url, VALID_PARAMETERS.v0, VALID_PARAMETERS.v1
6✔
454
                ))
455
                .send()
456
                .await?;
9✔
457
            assert_eq!(
3✔
458
                valid_extra_typed_path_response.status(),
6✔
459
                expected_valid_status,
460
                "Validified '{}' test failed.",
461
                extra_typed_path_type_name
462
            );
463

464
            let error_extra_typed_path_response = test_executor
12✔
465
                .client()
466
                .get(format!("{}/{route}/not_i32/path", server_url))
9✔
467
                .send()
468
                .await?;
9✔
469
            assert_eq!(
3✔
470
                error_extra_typed_path_response.status(),
6✔
471
                expected_error_status,
472
                "Error '{}' test failed.",
473
                extra_typed_path_type_name
474
            );
475

476
            let invalid_extra_typed_path_response = test_executor
12✔
477
                .client()
478
                .get(format!(
21✔
479
                    "{}/{route}/{}/{}",
480
                    server_url, INVALID_PARAMETERS.v0, INVALID_PARAMETERS.v1
6✔
481
                ))
482
                .send()
483
                .await?;
9✔
484
            assert_eq!(
3✔
485
                invalid_extra_typed_path_response.status(),
6✔
486
                expected_invalid_status,
487
                "Invalid '{}' test failed.",
488
                extra_typed_path_type_name
489
            );
490
            #[cfg(feature = "into_json")]
491
            if should_check_json {
2✔
492
                check_json(
493
                    extra_typed_path_type_name,
2✔
494
                    invalid_extra_typed_path_response,
2✔
495
                )
496
                .await;
2✔
497
            }
498
            println!("All {} tests passed.", extra_typed_path_type_name);
6✔
499
            Ok(())
3✔
500
        }
501

502
        test_extra_typed_path(&test_executor, "extra_typed_path", &server_url).await?;
9✔
503
        test_extra_typed_path_modified(&test_executor, "extra_typed_path_modified", &server_url)
12✔
504
            .await?;
9✔
505
        test_extra_typed_path(
506
            &test_executor,
3✔
507
            "extra_typed_path_validified_by_ref",
508
            &server_url,
3✔
509
        )
510
        .await?;
9✔
511
    }
512

513
    #[cfg(feature = "extra_query")]
514
    {
515
        use axum_extra::extract::Query;
516
        test_executor
12✔
517
            .execute::<Query<ParametersValidify>>(Method::POST, extra_query::route::EXTRA_QUERY)
3✔
518
            .await?;
9✔
519
    }
520

521
    #[cfg(feature = "extra_form")]
522
    {
523
        use axum_extra::extract::Form;
524
        test_executor
12✔
525
            .execute::<Form<ParametersValidify>>(Method::POST, extra_form::route::EXTRA_FORM)
3✔
526
            .await?;
9✔
527
    }
528

529
    #[cfg(feature = "extra_protobuf")]
530
    {
531
        use axum_extra::protobuf::Protobuf;
532
        // Validated
533
        test_executor
12✔
534
            .execute::<Protobuf<ParametersValidify>>(
535
                Method::POST,
3✔
536
                extra_protobuf::route::EXTRA_PROTOBUF,
537
            )
538
            .await?;
9✔
539
        // Modified
540
        test_executor
12✔
541
            .execute_modified::<Protobuf<ParametersValidify>>(
542
                Method::POST,
3✔
543
                extra_protobuf::route::EXTRA_PROTOBUF_MODIFIED,
544
            )
545
            .await?;
9✔
546
        // ValidifiedByRef
547
        test_executor
12✔
548
            .execute::<Protobuf<ParametersValidify>>(
549
                Method::POST,
3✔
550
                extra_protobuf::route::EXTRA_PROTOBUF_VALIDIFIED_BY_REF,
551
            )
552
            .await?;
9✔
553
    }
554

555
    #[cfg(feature = "yaml")]
556
    {
557
        use axum_yaml::Yaml;
558
        test_executor
12✔
559
            .execute::<Yaml<ParametersValidify>>(Method::POST, yaml::route::YAML)
3✔
560
            .await?;
9✔
561
    }
562

563
    #[cfg(feature = "msgpack")]
564
    {
565
        use axum_msgpack::{MsgPack, MsgPackRaw};
566
        test_executor
12✔
567
            .execute::<MsgPack<ParametersValidify>>(Method::POST, msgpack::route::MSGPACK)
3✔
568
            .await?;
9✔
569
        test_executor
12✔
570
            .execute::<MsgPackRaw<ParametersValidify>>(Method::POST, msgpack::route::MSGPACK_RAW)
3✔
571
            .await?;
9✔
572
    }
573

574
    drop(server_guard);
3✔
575
    server_handle.await??;
6✔
576
    Ok(())
6✔
577
}
578

579
#[derive(Debug, Clone)]
580
pub struct TestExecutor {
581
    client: reqwest::Client,
582
    server_url: Url,
583
}
584

585
impl From<Url> for TestExecutor {
586
    fn from(server_url: Url) -> Self {
3✔
587
        Self {
588
            client: Default::default(),
3✔
589
            server_url,
590
        }
591
    }
592
}
593

594
impl TestExecutor {
595
    /// Execute all tests
596
    pub async fn execute<T: ValidTest>(&self, method: Method, route: &str) -> anyhow::Result<()> {
225✔
597
        self.do_execute::<T>(
90✔
598
            method,
×
599
            route,
×
600
            StatusCode::OK,
×
601
            T::ERROR_STATUS_CODE,
×
602
            T::INVALID_STATUS_CODE,
×
603
            true,
604
        )
605
        .await
135✔
606
    }
607

608
    /// Execute all tests for `Modified` without validation
609
    pub async fn execute_modified<T: ValidTest>(
6✔
610
        &self,
611
        method: Method,
612
        route: &str,
613
    ) -> anyhow::Result<()> {
614
        self.do_execute::<T>(
12✔
615
            method,
×
616
            route,
×
617
            StatusCode::OK,
×
618
            T::ERROR_STATUS_CODE,
×
619
            StatusCode::OK,
×
620
            false,
621
        )
622
        .await
18✔
623
    }
624

625
    /// Execute all tests for `Modified` without validation
626
    pub async fn execute_validified<T: ValidTest>(
3✔
627
        &self,
628
        method: Method,
629
        route: &str,
630
    ) -> anyhow::Result<()> {
631
        self.do_execute::<T>(
6✔
632
            method,
×
633
            route,
×
634
            StatusCode::OK,
×
635
            T::INVALID_STATUS_CODE,
×
636
            T::INVALID_STATUS_CODE,
×
637
            false,
638
        )
639
        .await
9✔
640
    }
641

642
    async fn do_execute<T: ValidTest>(
45✔
643
        &self,
644
        method: Method,
645
        route: &str,
646
        expected_valid_status: StatusCode,
647
        expected_error_status: StatusCode,
648
        expected_invalid_status: StatusCode,
649
        should_check_json: bool,
650
    ) -> anyhow::Result<()> {
651
        let url = {
×
652
            let mut url_builder = self.server_url.clone();
45✔
653
            url_builder.set_path(route);
45✔
654
            url_builder
45✔
655
        };
656

657
        let type_name = type_name::<T>();
90✔
658

659
        let valid_builder = self.client.request(method.clone(), url.clone());
90✔
660
        let valid_response = T::set_valid_request(valid_builder).send().await?;
135✔
661
        assert_eq!(
45✔
662
            valid_response.status(),
90✔
663
            expected_valid_status,
×
664
            "Validified '{}' test failed: {}.",
665
            type_name,
×
666
            valid_response.text().await?
×
667
        );
668

669
        let error_builder = self.client.request(method.clone(), url.clone());
90✔
670
        let error_response = T::set_error_request(error_builder).send().await?;
135✔
671
        assert_eq!(
45✔
672
            error_response.status(),
90✔
673
            expected_error_status,
×
674
            "Error '{}' test failed: {}.",
675
            type_name,
×
676
            error_response.text().await?
×
677
        );
678

679
        let invalid_builder = self.client.request(method, url);
45✔
680
        let invalid_response = T::set_invalid_request(invalid_builder).send().await?;
135✔
681
        assert_eq!(
45✔
682
            invalid_response.status(),
90✔
683
            expected_invalid_status,
×
684
            "Invalid '{}' test failed: {}.",
685
            type_name,
×
686
            invalid_response.text().await?
×
687
        );
688
        #[cfg(feature = "into_json")]
×
689
        if should_check_json && T::JSON_SERIALIZABLE {
34✔
690
            check_json(type_name, invalid_response).await;
28✔
691
        }
692

693
        println!("All '{}' tests passed.", type_name);
90✔
694
        Ok(())
45✔
695
    }
696

697
    pub fn client(&self) -> &reqwest::Client {
3✔
698
        &self.client
3✔
699
    }
700
}
701

702
/// Check if the response is a json response
703
#[cfg(feature = "into_json")]
704
pub async fn check_json(type_name: &'static str, response: reqwest::Response) {
12✔
705
    assert_eq!(
2✔
706
        response.headers()[axum::http::header::CONTENT_TYPE],
4✔
707
        axum::http::HeaderValue::from_static(mime::APPLICATION_JSON.as_ref()),
2✔
708
        "'{}' rejection into json test failed",
709
        type_name
710
    );
711
    assert!(response.json::<serde_json::Value>().await.is_ok());
2✔
712
}
713

714
mod route {
715
    pub const PATH: &str = "/path/:v0/:v1";
716
    pub const PATH_MODIFIED: &str = "/path_modified/:v0/:v1";
717
    pub const PATH_VALIDIFIED: &str = "/path_validified/:v0/:v1";
718
    pub const PATH_VALIDIFIED_BY_REF: &str = "/path_validified_by_ref/:v0/:v1";
719
    pub const QUERY: &str = "/query";
720
    pub const QUERY_MODIFIED: &str = "/query_modified/:v0/:v1";
721

722
    pub const QUERY_VALIDIFIED: &str = "/query_validified/:v0/:v1";
723
    pub const QUERY_VALIDIFIED_BY_REF: &str = "/query_validified_by_ref/:v0/:v1";
724
    pub const FORM: &str = "/form";
725
    pub const FORM_MODIFIED: &str = "/form_modified/:v0/:v1";
726
    pub const FORM_VALIDIFIED: &str = "/form_validified/:v0/:v1";
727
    pub const FORM_VALIDIFIED_BY_REF: &str = "/form_validified_by_ref/:v0/:v1";
728
    pub const JSON: &str = "/json";
729
    pub const JSON_MODIFIED: &str = "/json_modified/:v0/:v1";
730
    pub const JSON_VALIDIFIED: &str = "/json_validified/:v0/:v1";
731
    pub const JSON_VALIDIFIED_BY_REF: &str = "/json_validified_by_ref/:v0/:v1";
732
}
733

734
async fn extract_path(
3✔
735
    Validated(Path(parameters)): Validated<Path<ParametersValidify>>,
736
) -> StatusCode {
737
    check_validated(&parameters)
3✔
738
}
739

740
async fn extract_path_modified(
3✔
741
    Modified(Path(parameters)): Modified<Path<ParametersValidify>>,
742
) -> StatusCode {
743
    check_modified(&parameters)
3✔
744
}
745

746
async fn extract_path_validified(
3✔
747
    Validified(Path(parameters)): Validified<Path<ParametersValidify>>,
748
) -> StatusCode {
749
    check_validified(&parameters)
3✔
750
}
751

752
async fn extract_path_validified_by_ref(
3✔
753
    ValidifiedByRef(Path(parameters)): ValidifiedByRef<Path<ParametersValidify>>,
754
) -> StatusCode {
755
    check_validified(&parameters)
3✔
756
}
757

758
async fn extract_query(
3✔
759
    Validated(Query(parameters)): Validated<Query<ParametersValidify>>,
760
) -> StatusCode {
761
    check_validated(&parameters)
3✔
762
}
763

764
async fn extract_query_modified(
3✔
765
    Modified(Query(parameters)): Modified<Query<ParametersValidify>>,
766
) -> StatusCode {
767
    check_modified(&parameters)
3✔
768
}
769

770
async fn extract_query_validified(
3✔
771
    Validified(Query(parameters)): Validified<Query<ParametersValidify>>,
772
) -> StatusCode {
773
    check_validified(&parameters)
3✔
774
}
775

776
async fn extract_query_validified_by_ref(
3✔
777
    ValidifiedByRef(Query(parameters)): ValidifiedByRef<Query<ParametersValidify>>,
778
) -> StatusCode {
779
    check_validified(&parameters)
3✔
780
}
781

782
async fn extract_form(
3✔
783
    Validated(Form(parameters)): Validated<Form<ParametersValidify>>,
784
) -> StatusCode {
785
    check_validated(&parameters)
3✔
786
}
787

788
async fn extract_form_modified(
×
789
    Modified(Form(parameters)): Modified<Form<ParametersValidify>>,
790
) -> StatusCode {
791
    check_modified(&parameters)
×
792
}
793

794
async fn extract_form_validified(
×
795
    Validified(Form(parameters)): Validified<Form<ParametersValidify>>,
796
) -> StatusCode {
797
    check_validified(&parameters)
×
798
}
799

800
async fn extract_form_validified_by_ref(
×
801
    ValidifiedByRef(Form(parameters)): ValidifiedByRef<Form<ParametersValidify>>,
802
) -> StatusCode {
803
    check_validified(&parameters)
×
804
}
805

806
async fn extract_json(
3✔
807
    Validated(Json(parameters)): Validated<Json<ParametersValidify>>,
808
) -> StatusCode {
809
    check_validated(&parameters)
3✔
810
}
811

812
async fn extract_json_modified(
×
813
    Modified(Json(parameters)): Modified<Json<ParametersValidify>>,
814
) -> StatusCode {
815
    check_modified(&parameters)
×
816
}
817

818
async fn extract_json_validified(
×
819
    Validified(Json(parameters)): Validified<Json<ParametersValidify>>,
820
) -> StatusCode {
821
    check_validified(&parameters)
×
822
}
823

824
async fn extract_json_validified_by_ref(
×
825
    ValidifiedByRef(Json(parameters)): ValidifiedByRef<Json<ParametersValidify>>,
826
) -> StatusCode {
827
    check_validified(&parameters)
×
828
}
829

830
fn check_validated<V: Validate>(validate: &V) -> StatusCode {
9✔
831
    // The `Validified` extractor has validated the `parameters` once,
832
    // it should have returned `400 BAD REQUEST` if the `parameters` were invalid,
833
    // Let's validate them again to check if the `Validified` extractor works well.
834
    // If it works properly, this function will never return `500 INTERNAL SERVER ERROR`
835
    match validate.validate() {
9✔
836
        Ok(_) => StatusCode::OK,
9✔
837
        Err(_) => StatusCode::INTERNAL_SERVER_ERROR,
×
838
    }
839
}
840

841
fn check_modified<M: IsModified>(modify: &M) -> StatusCode {
9✔
842
    if modify.modified() {
9✔
843
        StatusCode::OK
9✔
844
    } else {
845
        StatusCode::INTERNAL_SERVER_ERROR
×
846
    }
847
}
848

849
fn check_validified<D: IsModified + Validate>(data: &D) -> StatusCode {
6✔
850
    let status = check_modified(data);
6✔
851
    if status != StatusCode::OK {
6✔
852
        return status;
×
853
    }
854

855
    check_validated(data)
6✔
856
}
857

858
#[cfg(feature = "typed_header")]
859
mod typed_header {
860

861
    pub(crate) mod route {
862
        pub const TYPED_HEADER: &str = "/typed_header";
863
    }
864

865
    use super::{check_validated, ParametersValidify};
866
    use crate::Validated;
867
    use axum::headers::{Error, Header, HeaderName, HeaderValue};
868
    use axum::http::StatusCode;
869
    use axum::TypedHeader;
870

871
    pub static AXUM_VALID_PARAMETERS: HeaderName = HeaderName::from_static("axum-valid-parameters");
872

873
    pub(super) async fn extract_typed_header(
3✔
874
        Validated(TypedHeader(parameters)): Validated<TypedHeader<ParametersValidify>>,
875
    ) -> StatusCode {
876
        check_validated(&parameters)
3✔
877
    }
878

879
    impl Header for ParametersValidify {
880
        fn name() -> &'static HeaderName {
881
            &AXUM_VALID_PARAMETERS
882
        }
883

884
        fn decode<'i, I>(values: &mut I) -> Result<Self, Error>
6✔
885
        where
886
            Self: Sized,
887
            I: Iterator<Item = &'i HeaderValue>,
888
        {
889
            let value = values.next().ok_or_else(Error::invalid)?;
9✔
890
            let src = std::str::from_utf8(value.as_bytes()).map_err(|_| Error::invalid())?;
12✔
891
            let split = src.split(',').collect::<Vec<_>>();
6✔
892
            match split.as_slice() {
6✔
893
                [v0, v1] => Ok(ParametersValidify {
18✔
894
                    v0: v0.parse().map_err(|_| Error::invalid())?,
18✔
895
                    v1: v1.to_string(),
6✔
896
                }),
897
                _ => Err(Error::invalid()),
×
898
            }
899
        }
900

901
        fn encode<E: Extend<HeaderValue>>(&self, values: &mut E) {
6✔
902
            let v0 = self.v0.to_string();
6✔
903
            let mut vec = Vec::with_capacity(v0.len() + 1 + self.v1.len());
12✔
904
            vec.extend_from_slice(v0.as_bytes());
12✔
905
            vec.push(b',');
6✔
906
            vec.extend_from_slice(self.v1.as_bytes());
6✔
907
            let value = HeaderValue::from_bytes(&vec).expect("Failed to build header");
6✔
908
            values.extend(::std::iter::once(value));
6✔
909
        }
910
    }
911

912
    #[test]
913
    fn parameter_is_header() -> anyhow::Result<()> {
914
        let parameter = ParametersValidify {
915
            v0: 123456,
916
            v1: "111111".to_string(),
917
        };
918
        let mut vec = Vec::new();
919
        parameter.encode(&mut vec);
920
        let mut iter = vec.iter();
921
        assert_eq!(parameter, ParametersValidify::decode(&mut iter)?);
922
        Ok(())
923
    }
924
}
925

926
#[cfg(feature = "typed_multipart")]
927
mod typed_multipart {
928
    use super::{check_validated, ParametersValidify};
929
    use crate::Validated;
930
    use axum::http::StatusCode;
931
    use axum_typed_multipart::{BaseMultipart, TypedMultipart, TypedMultipartError};
932

933
    pub mod route {
934
        pub const TYPED_MULTIPART: &str = "/typed_multipart";
935
        pub const BASE_MULTIPART: &str = "/base_multipart";
936
    }
937

938
    impl From<&ParametersValidify> for reqwest::multipart::Form {
939
        fn from(value: &ParametersValidify) -> Self {
3✔
940
            reqwest::multipart::Form::new()
9✔
941
                .text("v0", value.v0.to_string())
6✔
942
                .text("v1", value.v1.clone())
6✔
943
        }
944
    }
945

946
    pub(super) async fn extract_typed_multipart(
3✔
947
        Validated(TypedMultipart(parameters)): Validated<TypedMultipart<ParametersValidify>>,
948
    ) -> StatusCode {
949
        check_validated(&parameters)
3✔
950
    }
951

952
    pub(super) async fn extract_base_multipart(
3✔
953
        Validated(BaseMultipart { data, .. }): Validated<
954
            BaseMultipart<ParametersValidify, TypedMultipartError>,
955
        >,
956
    ) -> StatusCode {
957
        check_validated(&data)
3✔
958
    }
959
}
960

961
#[cfg(feature = "extra")]
962
mod extra {
963
    use super::{check_validated, ParametersValidify};
964
    use crate::tests::{Rejection, ValidTest, ValidTestParameter};
965
    use crate::{Validated, ValidifyRejection};
966
    use axum::extract::FromRequestParts;
967
    use axum::http::request::Parts;
968
    use axum::http::StatusCode;
969
    use axum::response::{IntoResponse, Response};
970
    use axum_extra::extract::{Cached, WithRejection};
971
    use reqwest::RequestBuilder;
972

973
    pub mod route {
974
        pub const CACHED: &str = "/cached";
975
        pub const WITH_REJECTION: &str = "/with_rejection";
976
        pub const WITH_REJECTION_VALIDIFY: &str = "/with_rejection_validify";
977
    }
978
    pub const PARAMETERS_HEADER: &str = "parameters-header";
979
    pub const CACHED_REJECTION_STATUS: StatusCode = StatusCode::FORBIDDEN;
980

981
    //  1.2. Define you own `Rejection` type and implement `IntoResponse` for it.
982
    pub enum ParametersRejection {
983
        Null,
984
        InvalidJson(serde_json::error::Error),
985
    }
986

987
    impl IntoResponse for ParametersRejection {
988
        fn into_response(self) -> Response {
3✔
989
            match self {
3✔
990
                ParametersRejection::Null => {
991
                    (CACHED_REJECTION_STATUS, "My-Data header is missing").into_response()
×
992
                }
993
                ParametersRejection::InvalidJson(e) => (
6✔
994
                    CACHED_REJECTION_STATUS,
995
                    format!("My-Data is not valid json string: {e}"),
3✔
996
                )
997
                    .into_response(),
998
            }
999
        }
1000
    }
1001

1002
    //  1.3. Implement your extractor (`FromRequestParts` or `FromRequest`)
1003
    #[axum::async_trait]
1004
    impl<S> FromRequestParts<S> for ParametersValidify
1005
    where
1006
        S: Send + Sync,
1007
    {
1008
        type Rejection = ParametersRejection;
1009

1010
        async fn from_request_parts(parts: &mut Parts, _: &S) -> Result<Self, Self::Rejection> {
15✔
1011
            let Some(value) = parts.headers.get(PARAMETERS_HEADER) else {
3✔
1012
                return Err(ParametersRejection::Null);
×
1013
            };
1014

1015
            serde_json::from_slice(value.as_bytes()).map_err(ParametersRejection::InvalidJson)
6✔
1016
        }
1017
    }
1018

1019
    impl ValidTest for ParametersValidify {
1020
        const ERROR_STATUS_CODE: StatusCode = CACHED_REJECTION_STATUS;
1021

1022
        fn set_valid_request(builder: RequestBuilder) -> RequestBuilder {
3✔
1023
            builder.header(
6✔
1024
                PARAMETERS_HEADER,
1025
                serde_json::to_string(ParametersValidify::valid())
6✔
1026
                    .expect("Failed to serialize parameters"),
1027
            )
1028
        }
1029

1030
        fn set_error_request(builder: RequestBuilder) -> RequestBuilder {
3✔
1031
            builder.header(
6✔
1032
                PARAMETERS_HEADER,
1033
                serde_json::to_string(ParametersValidify::error())
6✔
1034
                    .expect("Failed to serialize parameters"),
1035
            )
1036
        }
1037

1038
        fn set_invalid_request(builder: RequestBuilder) -> RequestBuilder {
3✔
1039
            builder.header(
6✔
1040
                PARAMETERS_HEADER,
1041
                serde_json::to_string(ParametersValidify::invalid())
6✔
1042
                    .expect("Failed to serialize parameters"),
1043
            )
1044
        }
1045
    }
1046

1047
    pub struct ValidifyWithRejectionRejection {
1048
        inner: ParametersRejection,
1049
    }
1050

1051
    impl Rejection for ValidifyWithRejectionRejection {
1052
        const STATUS_CODE: StatusCode = StatusCode::CONFLICT;
1053
    }
1054

1055
    impl IntoResponse for ValidifyWithRejectionRejection {
1056
        fn into_response(self) -> Response {
3✔
1057
            let mut response = self.inner.into_response();
3✔
1058
            *response.status_mut() = Self::STATUS_CODE;
6✔
1059
            response
3✔
1060
        }
1061
    }
1062

1063
    // satisfy the `WithRejection`'s extractor trait bound
1064
    // R: From<E::Rejection> + IntoResponse
1065
    impl From<ParametersRejection> for ValidifyWithRejectionRejection {
1066
        fn from(inner: ParametersRejection) -> Self {
3✔
1067
            Self { inner }
1068
        }
1069
    }
1070

1071
    pub async fn extract_cached(
3✔
1072
        Validated(Cached(parameters)): Validated<Cached<ParametersValidify>>,
1073
    ) -> StatusCode {
1074
        check_validated(&parameters)
3✔
1075
    }
1076

1077
    pub async fn extract_with_rejection(
3✔
1078
        Validated(WithRejection(parameters, _)): Validated<
1079
            WithRejection<ParametersValidify, ValidifyWithRejectionRejection>,
1080
        >,
1081
    ) -> StatusCode {
1082
        check_validated(&parameters)
3✔
1083
    }
1084

1085
    pub struct WithRejectionValidifyRejection<E> {
1086
        inner: ValidifyRejection<E>,
1087
    }
1088

1089
    impl<E> From<ValidifyRejection<E>> for WithRejectionValidifyRejection<E> {
1090
        fn from(inner: ValidifyRejection<E>) -> Self {
3✔
1091
            Self { inner }
1092
        }
1093
    }
1094

1095
    impl<E: IntoResponse> IntoResponse for WithRejectionValidifyRejection<E> {
1096
        fn into_response(self) -> Response {
3✔
1097
            let mut res = self.inner.into_response();
3✔
1098
            *res.status_mut() = StatusCode::IM_A_TEAPOT;
6✔
1099
            res
3✔
1100
        }
1101
    }
1102

1103
    pub async fn extract_with_rejection_valid(
3✔
1104
        WithRejection(Validated(parameters), _): WithRejection<
1105
            Validated<ParametersValidify>,
1106
            WithRejectionValidifyRejection<ParametersRejection>,
1107
        >,
1108
    ) -> StatusCode {
1109
        check_validated(&parameters)
3✔
1110
    }
1111
}
1112

1113
#[cfg(feature = "extra_typed_path")]
1114
mod extra_typed_path {
1115
    use super::{check_modified, check_validated, check_validified};
1116
    use crate::{HasModify, HasValidate, Modified, Validated, ValidifiedByRef};
1117
    use axum::http::StatusCode;
1118
    use axum_extra::routing::TypedPath;
1119
    use serde::Deserialize;
1120
    use validify::{Validate, Validify};
1121

1122
    pub mod route {
1123
        pub const EXTRA_TYPED_PATH: &str = "/extra_typed_path/:v0/:v1";
1124
        pub const EXTRA_TYPED_PATH_MODIFIED: &str = "/extra_typed_path_modified/:v0/:v1";
1125
        pub const EXTRA_TYPED_PATH_VALIDIFIED_BY_REF: &str =
1126
            "/extra_typed_path_validified_by_ref/:v0/:v1";
1127
    }
1128

1129
    #[derive(Validate, TypedPath, Deserialize)]
1130
    #[typed_path("/extra_typed_path/:v0/:v1")]
1131
    pub struct TypedPathParam {
1132
        #[validate(range(min = 5.0, max = 10.0))]
1133
        v0: i32,
1134
        #[validate(length(min = 1, max = 10))]
1135
        v1: String,
1136
    }
1137

1138
    impl HasValidate for TypedPathParam {
1139
        type Validate = Self;
1140

1141
        fn get_validate(&self) -> &Self::Validate {
3✔
1142
            self
1143
        }
1144
    }
1145

1146
    #[derive(Validify, TypedPath, Deserialize, Clone, PartialEq, Eq)]
1147
    #[typed_path("/extra_typed_path_validified_by_ref/:v0/:v1")]
1148
    pub struct TypedPathParamValidifiedByRef {
1149
        #[validate(range(min = 5.0, max = 10.0))]
1150
        v0: i32,
1151
        #[modify(lowercase)]
1152
        #[validate(length(min = 1, max = 10))]
1153
        v1: String,
1154
    }
1155

1156
    impl HasValidate for TypedPathParamValidifiedByRef {
1157
        type Validate = Self;
1158

1159
        fn get_validate(&self) -> &Self::Validate {
3✔
1160
            self
1161
        }
1162
    }
1163

1164
    impl HasModify for TypedPathParamValidifiedByRef {
1165
        type Modify = Self;
1166

1167
        fn get_modify(&mut self) -> &mut Self::Modify {
3✔
1168
            self
1169
        }
1170
    }
1171

1172
    #[derive(Validify, TypedPath, Deserialize, Clone, PartialEq, Eq)]
1173
    #[typed_path("/extra_typed_path_modified/:v0/:v1")]
1174
    pub struct TypedPathParamModified {
1175
        #[validate(range(min = 5.0, max = 10.0))]
1176
        v0: i32,
1177
        #[modify(lowercase)]
1178
        #[validate(length(min = 1, max = 10))]
1179
        v1: String,
1180
    }
1181

1182
    impl HasModify for TypedPathParamModified {
1183
        type Modify = Self;
1184

1185
        fn get_modify(&mut self) -> &mut Self::Modify {
3✔
1186
            self
1187
        }
1188
    }
1189

1190
    pub async fn extract_extra_typed_path(
3✔
1191
        Validated(param): Validated<TypedPathParam>,
1192
    ) -> StatusCode {
1193
        check_validated(&param)
3✔
1194
    }
1195

1196
    pub async fn extract_extra_typed_path_modified(
3✔
1197
        Modified(param): Modified<TypedPathParamModified>,
1198
    ) -> StatusCode {
1199
        check_modified(&param)
3✔
1200
    }
1201

1202
    pub async fn extract_extra_typed_path_validified_by_ref(
3✔
1203
        ValidifiedByRef(param): ValidifiedByRef<TypedPathParamValidifiedByRef>,
1204
    ) -> StatusCode {
1205
        check_validified(&param)
3✔
1206
    }
1207
}
1208

1209
#[cfg(feature = "extra_query")]
1210
mod extra_query {
1211
    use super::{check_validated, ParametersValidify};
1212
    use crate::Validated;
1213
    use axum::http::StatusCode;
1214
    use axum_extra::extract::Query;
1215

1216
    pub mod route {
1217
        pub const EXTRA_QUERY: &str = "/extra_query";
1218
    }
1219

1220
    pub async fn extract_extra_query(
3✔
1221
        Validated(Query(parameters)): Validated<Query<ParametersValidify>>,
1222
    ) -> StatusCode {
1223
        check_validated(&parameters)
3✔
1224
    }
1225
}
1226

1227
#[cfg(feature = "extra_form")]
1228
mod extra_form {
1229
    use super::{check_validated, ParametersValidify};
1230
    use crate::Validated;
1231
    use axum::http::StatusCode;
1232
    use axum_extra::extract::Form;
1233

1234
    pub mod route {
1235
        pub const EXTRA_FORM: &str = "/extra_form";
1236
    }
1237

1238
    pub async fn extract_extra_form(
3✔
1239
        Validated(Form(parameters)): Validated<Form<ParametersValidify>>,
1240
    ) -> StatusCode {
1241
        check_validated(&parameters)
3✔
1242
    }
1243
}
1244

1245
#[cfg(feature = "extra_protobuf")]
1246
mod extra_protobuf {
1247
    use super::{check_modified, check_validated, check_validified, ParametersValidify};
1248
    use crate::{Modified, Validated, ValidifiedByRef};
1249
    use axum::http::StatusCode;
1250
    use axum_extra::protobuf::Protobuf;
1251

1252
    pub mod route {
1253
        pub const EXTRA_PROTOBUF: &str = "/extra_protobuf";
1254
        pub const EXTRA_PROTOBUF_MODIFIED: &str = "/extra_protobuf_modified";
1255
        pub const EXTRA_PROTOBUF_VALIDIFIED_BY_REF: &str = "/extra_protobuf_validified_by_ref";
1256
    }
1257

1258
    pub async fn extract_extra_protobuf(
3✔
1259
        Validated(Protobuf(parameters)): Validated<Protobuf<ParametersValidify>>,
1260
    ) -> StatusCode {
1261
        check_validated(&parameters)
3✔
1262
    }
1263

1264
    pub async fn extract_extra_protobuf_modified(
3✔
1265
        Modified(Protobuf(parameters)): Modified<Protobuf<ParametersValidify>>,
1266
    ) -> StatusCode {
1267
        check_modified(&parameters)
3✔
1268
    }
1269

1270
    pub async fn extract_extra_protobuf_validified_by_ref(
3✔
1271
        ValidifiedByRef(Protobuf(parameters)): ValidifiedByRef<Protobuf<ParametersValidify>>,
1272
    ) -> StatusCode {
1273
        check_validified(&parameters)
3✔
1274
    }
1275
}
1276

1277
#[cfg(feature = "yaml")]
1278
mod yaml {
1279
    use super::{check_validated, ParametersValidify};
1280
    use crate::Validated;
1281
    use axum::http::StatusCode;
1282
    use axum_yaml::Yaml;
1283

1284
    pub mod route {
1285
        pub const YAML: &str = "/yaml";
1286
    }
1287

1288
    pub async fn extract_yaml(
3✔
1289
        Validated(Yaml(parameters)): Validated<Yaml<ParametersValidify>>,
1290
    ) -> StatusCode {
1291
        check_validated(&parameters)
3✔
1292
    }
1293
}
1294

1295
#[cfg(feature = "msgpack")]
1296
mod msgpack {
1297
    use super::{check_validated, ParametersValidify};
1298
    use crate::Validated;
1299
    use axum::http::StatusCode;
1300
    use axum_msgpack::{MsgPack, MsgPackRaw};
1301

1302
    pub mod route {
1303
        pub const MSGPACK: &str = "/msgpack";
1304
        pub const MSGPACK_RAW: &str = "/msgpack_raw";
1305
    }
1306

1307
    pub async fn extract_msgpack(
3✔
1308
        Validated(MsgPack(parameters)): Validated<MsgPack<ParametersValidify>>,
1309
    ) -> StatusCode {
1310
        check_validated(&parameters)
3✔
1311
    }
1312
    pub async fn extract_msgpack_raw(
3✔
1313
        Validated(MsgPackRaw(parameters)): Validated<MsgPackRaw<ParametersValidify>>,
1314
    ) -> StatusCode {
1315
        check_validated(&parameters)
3✔
1316
    }
1317
}
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