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

gengteng / axum-valid / 8105806959

01 Mar 2024 02:47AM UTC coverage: 90.139% (+0.09%) from 90.052%
8105806959

push

github

gengteng
fix: Use conditional compilation for 'sonic' module

1 of 1 new or added line in 1 file covered. (100.0%)

65 existing lines in 4 files now uncovered.

1618 of 1795 relevant lines covered (90.14%)

15.1 hits per line

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

95.2
/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::http::StatusCode;
9
use axum::routing::{get, post};
10
use axum::{Form, Json, Router};
11
use once_cell::sync::Lazy;
12
#[cfg(feature = "extra_protobuf")]
13
use prost::Message;
14
use reqwest::{Method, Url};
15
use serde::{Deserialize, Serialize};
16
use std::any::type_name;
17
use std::net::SocketAddr;
18
use std::ops::Deref;
19
use tokio::net::TcpListener;
20
use validify::{Modify, Payload, Validate, Validify};
21

22
#[derive(Debug, Clone, Deserialize, Serialize, Validify, Payload, Eq, PartialEq)]
23
pub struct ParametersValidify {
24
    #[validate(range(min = 5.0, max = 10.0))]
25
    v0: i32,
26
    #[modify(lowercase)]
27
    #[validate(length(min = 1, max = 10))]
28
    v1: String,
29
}
30

31
#[derive(Clone, Validify, Eq, PartialEq)]
32
#[cfg_attr(feature = "extra_protobuf", derive(Message))]
33
#[cfg_attr(
34
    feature = "typed_multipart",
35
    derive(axum_typed_multipart::TryFromMultipart)
36
)]
37
pub struct ParametersValidifyWithoutPayload {
38
    #[validate(range(min = 5.0, max = 10.0))]
39
    #[cfg_attr(feature = "extra_protobuf", prost(int32, tag = "1"))]
40
    v0: i32,
41
    #[modify(lowercase)]
42
    #[validate(length(min = 1, max = 10))]
43
    #[cfg_attr(feature = "extra_protobuf", prost(string, tag = "2"))]
44
    v1: String,
45
}
46

47
trait IsModified: Modify + Clone + PartialEq + Eq {
48
    fn modified(&self) -> bool {
12✔
49
        let mut cloned = self.clone();
12✔
50
        cloned.modify();
12✔
51
        cloned == *self
12✔
52
    }
53
}
54

55
impl<T> IsModified for T where T: Modify + Clone + PartialEq + Eq {}
56

57
static VALID_PARAMETERS: Lazy<ParametersValidify> = Lazy::new(|| ParametersValidify {
6✔
58
    v0: 5,
59
    v1: String::from("ABCDEFG"),
3✔
60
});
61

62
static INVALID_PARAMETERS: Lazy<ParametersValidify> = Lazy::new(|| ParametersValidify {
6✔
63
    v0: 6,
64
    v1: String::from("ABCDEFGHIJKLMN"),
3✔
65
});
66

67
static VALID_PARAMETERS_WITHOUT_PAYLOAD: Lazy<ParametersValidifyWithoutPayload> =
68
    Lazy::new(|| ParametersValidifyWithoutPayload {
6✔
69
        v0: 5,
70
        v1: String::from("ABCDEFG"),
3✔
71
    });
72

73
static INVALID_PARAMETERS_WITHOUT_PAYLOAD: Lazy<ParametersValidifyWithoutPayload> =
74
    Lazy::new(|| ParametersValidifyWithoutPayload {
6✔
75
        v0: 6,
76
        v1: String::from("ABCDEFGHIJKLMN"),
3✔
77
    });
78

79
impl ValidTestParameter for ParametersValidify {
80
    fn valid() -> &'static Self {
3✔
81
        VALID_PARAMETERS.deref()
3✔
82
    }
83

84
    fn error() -> &'static [(&'static str, &'static str)] {
85
        &[("not_v0_or_v1", "value")]
86
    }
87

88
    fn invalid() -> &'static Self {
3✔
89
        INVALID_PARAMETERS.deref()
3✔
90
    }
91
}
92

93
impl ValidTestParameter for ParametersValidifyWithoutPayload {
94
    fn valid() -> &'static Self {
3✔
95
        VALID_PARAMETERS_WITHOUT_PAYLOAD.deref()
3✔
96
    }
97

98
    fn error() -> &'static [(&'static str, &'static str)] {
99
        &[("not_v0_or_v1", "value")]
100
    }
101

102
    fn invalid() -> &'static Self {
3✔
103
        INVALID_PARAMETERS_WITHOUT_PAYLOAD.deref()
3✔
104
    }
105
}
106

107
impl HasValidate for ParametersValidify {
108
    type Validate = ParametersValidify;
109

110
    fn get_validate(&self) -> &Self::Validate {
3✔
111
        self
112
    }
113
}
114

115
#[tokio::test]
18✔
116
async fn test_main() -> anyhow::Result<()> {
9✔
117
    let router = Router::new()
54✔
118
        .route(route::PATH, get(extract_path))
6✔
119
        .route(route::PATH_MODIFIED, get(extract_path_modified))
6✔
120
        .route(route::PATH_VALIDIFIED, get(extract_path_validified))
6✔
121
        .route(
122
            route::PATH_VALIDIFIED_BY_REF,
123
            get(extract_path_validified_by_ref),
3✔
124
        )
125
        .route(route::QUERY, get(extract_query))
6✔
126
        .route(route::QUERY_MODIFIED, get(extract_query_modified))
6✔
127
        .route(route::QUERY_VALIDIFIED, get(extract_query_validified))
6✔
128
        .route(
129
            route::QUERY_VALIDIFIED_BY_REF,
130
            get(extract_query_validified_by_ref),
3✔
131
        )
132
        .route(route::FORM, post(extract_form))
6✔
133
        .route(route::FORM_MODIFIED, post(extract_form_modified))
6✔
134
        .route(route::FORM_VALIDIFIED, post(extract_form_validified))
6✔
135
        .route(
136
            route::FORM_VALIDIFIED_BY_REF,
137
            post(extract_form_validified_by_ref),
3✔
138
        )
139
        .route(route::JSON, post(extract_json))
6✔
140
        .route(route::JSON_MODIFIED, post(extract_json_modified))
6✔
141
        .route(route::JSON_VALIDIFIED, post(extract_json_validified))
6✔
142
        .route(
143
            route::JSON_VALIDIFIED_BY_REF,
144
            post(extract_json_validified_by_ref),
3✔
145
        );
146

147
    #[cfg(feature = "typed_header")]
148
    let router = router
12✔
149
        .route(
150
            typed_header::route::TYPED_HEADER,
151
            post(typed_header::extract_typed_header),
3✔
152
        )
153
        .route(
154
            typed_header::route::TYPED_HEADER_MODIFIED,
155
            post(typed_header::extract_typed_header_modified),
3✔
156
        )
157
        .route(
158
            typed_header::route::TYPED_HEADER_VALIDIFIED_BY_REF,
159
            post(typed_header::extract_typed_header_validified_by_ref),
3✔
160
        );
161

162
    #[cfg(feature = "typed_multipart")]
163
    let router = router
21✔
164
        .route(
165
            typed_multipart::route::TYPED_MULTIPART,
166
            post(typed_multipart::extract_typed_multipart),
3✔
167
        )
168
        .route(
169
            typed_multipart::route::TYPED_MULTIPART_MODIFIED,
170
            post(typed_multipart::extract_typed_multipart_modified),
3✔
171
        )
172
        .route(
173
            typed_multipart::route::TYPED_MULTIPART_VALIDIFIED_BY_REF,
174
            post(typed_multipart::extract_typed_multipart_validified_by_ref),
3✔
175
        )
176
        .route(
177
            typed_multipart::route::BASE_MULTIPART,
178
            post(typed_multipart::extract_base_multipart),
3✔
179
        )
180
        .route(
181
            typed_multipart::route::BASE_MULTIPART_MODIFIED,
182
            post(typed_multipart::extract_base_multipart_modified),
3✔
183
        )
184
        .route(
185
            typed_multipart::route::BASE_MULTIPART_VALIDIFIED_BY_REF,
186
            post(typed_multipart::extract_base_multipart_validified_by_ref),
3✔
187
        );
188

189
    #[cfg(feature = "extra")]
190
    let router = router
30✔
191
        .route(extra::route::CACHED, post(extra::extract_cached))
6✔
192
        .route(
193
            extra::route::CACHED_MODIFIED,
194
            post(extra::extract_cached_modified),
3✔
195
        )
196
        .route(
197
            extra::route::CACHED_VALIDIFIED_BY_REF,
198
            post(extra::extract_cached_validified_by_ref),
3✔
199
        )
200
        .route(
201
            extra::route::WITH_REJECTION,
202
            post(extra::extract_with_rejection),
3✔
203
        )
204
        .route(
205
            extra::route::WITH_REJECTION_MODIFIED,
206
            post(extra::extract_with_rejection_modified),
3✔
207
        )
208
        .route(
209
            extra::route::WITH_REJECTION_VALIDIFIED_BY_REF,
210
            post(extra::extract_with_rejection_validified_by_ref),
3✔
211
        )
212
        .route(
213
            extra::route::WITH_REJECTION_VALIDIFY,
214
            post(extra::extract_with_rejection_validifiy),
3✔
215
        )
216
        .route(
217
            extra::route::WITH_REJECTION_VALIDIFY_MODIFIED,
218
            post(extra::extract_with_rejection_validifiy_modified),
3✔
219
        )
220
        .route(
221
            extra::route::WITH_REJECTION_VALIDIFY_VALIDIFIED_BY_REF,
222
            post(extra::extract_with_rejection_validifiy_validified_by_ref),
3✔
223
        );
224

225
    #[cfg(feature = "extra_typed_path")]
226
    let router = router
12✔
227
        .route(
228
            extra_typed_path::route::EXTRA_TYPED_PATH,
229
            get(extra_typed_path::extract_extra_typed_path),
3✔
230
        )
231
        .route(
232
            extra_typed_path::route::EXTRA_TYPED_PATH_MODIFIED,
233
            get(extra_typed_path::extract_extra_typed_path_modified),
3✔
234
        )
235
        .route(
236
            extra_typed_path::route::EXTRA_TYPED_PATH_VALIDIFIED_BY_REF,
237
            get(extra_typed_path::extract_extra_typed_path_validified_by_ref),
3✔
238
        );
239

240
    #[cfg(feature = "extra_query")]
241
    let router = router
15✔
242
        .route(
243
            extra_query::route::EXTRA_QUERY,
244
            post(extra_query::extract_extra_query),
3✔
245
        )
246
        .route(
247
            extra_query::route::EXTRA_QUERY_MODIFIED,
248
            post(extra_query::extract_extra_query_modified),
3✔
249
        )
250
        .route(
251
            extra_query::route::EXTRA_QUERY_VALIDIFIED,
252
            post(extra_query::extract_extra_query_validified),
3✔
253
        )
254
        .route(
255
            extra_query::route::EXTRA_QUERY_VALIDIFIED_BY_REF,
256
            post(extra_query::extract_extra_query_validified_by_ref),
3✔
257
        );
258

259
    #[cfg(feature = "extra_form")]
260
    let router = router
15✔
261
        .route(
262
            extra_form::route::EXTRA_FORM,
263
            post(extra_form::extract_extra_form),
3✔
264
        )
265
        .route(
266
            extra_form::route::EXTRA_FORM_MODIFIED,
267
            post(extra_form::extract_extra_form_modified),
3✔
268
        )
269
        .route(
270
            extra_form::route::EXTRA_FORM_VALIDIFED,
271
            post(extra_form::extract_extra_form_validifed),
3✔
272
        )
273
        .route(
274
            extra_form::route::EXTRA_FORM_VALIDIFED_BY_REF,
275
            post(extra_form::extract_extra_form_validifed_by_ref),
3✔
276
        );
277

278
    #[cfg(feature = "extra_protobuf")]
279
    let router = router
12✔
280
        .route(
281
            extra_protobuf::route::EXTRA_PROTOBUF,
282
            post(extra_protobuf::extract_extra_protobuf),
3✔
283
        )
284
        .route(
285
            extra_protobuf::route::EXTRA_PROTOBUF_MODIFIED,
286
            post(extra_protobuf::extract_extra_protobuf_modified),
3✔
287
        )
288
        .route(
289
            extra_protobuf::route::EXTRA_PROTOBUF_VALIDIFIED_BY_REF,
290
            post(extra_protobuf::extract_extra_protobuf_validified_by_ref),
3✔
291
        );
292

293
    #[cfg(feature = "yaml")]
294
    let router = router
15✔
295
        .route(yaml::route::YAML, post(yaml::extract_yaml))
6✔
296
        .route(
297
            yaml::route::YAML_MODIFIED,
298
            post(yaml::extract_yaml_modified),
3✔
299
        )
300
        .route(
301
            yaml::route::YAML_VALIDIFIED,
302
            post(yaml::extract_yaml_validified),
3✔
303
        )
304
        .route(
305
            yaml::route::YAML_VALIDIFIED_BY_REF,
306
            post(yaml::extract_yaml_validified_by_ref),
3✔
307
        );
308

309
    #[cfg(feature = "msgpack")]
310
    let router = router
27✔
311
        .route(msgpack::route::MSGPACK, post(msgpack::extract_msgpack))
6✔
312
        .route(
313
            msgpack::route::MSGPACK_MODIFIED,
314
            post(msgpack::extract_msgpack_modified),
3✔
315
        )
316
        .route(
317
            msgpack::route::MSGPACK_VALIDIFIED,
318
            post(msgpack::extract_msgpack_validified),
3✔
319
        )
320
        .route(
321
            msgpack::route::MSGPACK_VALIDIFIED_BY_REF,
322
            post(msgpack::extract_msgpack_validified_by_ref),
3✔
323
        )
324
        .route(
325
            msgpack::route::MSGPACK_RAW,
326
            post(msgpack::extract_msgpack_raw),
3✔
327
        )
328
        .route(
329
            msgpack::route::MSGPACK_RAW_MODIFIED,
330
            post(msgpack::extract_msgpack_raw_modified),
3✔
331
        )
332
        .route(
333
            msgpack::route::MSGPACK_RAW_VALIDIFIED,
334
            post(msgpack::extract_msgpack_raw_validified),
3✔
335
        )
336
        .route(
337
            msgpack::route::MSGPACK_RAW_VALIDIFIED_BY_REF,
338
            post(msgpack::extract_msgpack_raw_validified_by_ref),
3✔
339
        );
340

341
    #[cfg(feature = "xml")]
342
    let router = router
15✔
343
        .route(xml::route::XML, post(xml::extract_xml))
6✔
344
        .route(xml::route::XML_MODIFIED, post(xml::extract_xml_modified))
6✔
345
        .route(
346
            xml::route::XML_VALIDIFIED,
347
            post(xml::extract_xml_validified),
3✔
348
        )
349
        .route(
350
            xml::route::XML_VALIDIFIED_BY_REF,
351
            post(xml::extract_xml_validified_by_ref),
3✔
352
        );
353

354
    #[cfg(feature = "toml")]
355
    let router = router
15✔
356
        .route(toml::route::TOML, post(toml::extract_toml))
6✔
357
        .route(
358
            toml::route::TOML_MODIFIED,
359
            post(toml::extract_toml_modified),
3✔
360
        )
361
        .route(
362
            toml::route::TOML_VALIDIFIED,
363
            post(toml::extract_toml_validified),
3✔
364
        )
365
        .route(
366
            toml::route::TOML_VALIDIFIED_BY_REF,
367
            post(toml::extract_toml_validified_by_ref),
3✔
368
        );
369

370
    #[cfg(feature = "sonic")]
371
    let router = router
15✔
372
        .route(sonic::route::SONIC, post(sonic::extract_sonic))
6✔
373
        .route(
374
            sonic::route::SONIC_MODIFIED,
375
            post(sonic::extract_sonic_modified),
3✔
376
        )
377
        .route(
378
            sonic::route::SONIC_VALIDIFIED,
379
            post(sonic::extract_sonic_validified),
3✔
380
        )
381
        .route(
382
            sonic::route::SONIC_VALIDIFIED_BY_REF,
383
            post(sonic::extract_sonic_validified_by_ref),
3✔
384
        );
385

386
    let listener = TcpListener::bind(&SocketAddr::from(([0u8, 0, 0, 0], 0u16))).await?;
6✔
387
    let server_addr = listener.local_addr()?;
6✔
388
    let server = axum::serve(listener, router.into_make_service());
3✔
389
    println!("Axum server address: {}.", server_addr);
6✔
390

391
    tokio::spawn(async move {
12✔
392
        let _ = server.await;
9✔
393
    });
394

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

398
    async fn test_extra_path(
3✔
399
        test_executor: &TestExecutor,
400
        route: &str,
401
        server_url: &str,
402
    ) -> anyhow::Result<()> {
403
        do_test_extra_path(
404
            test_executor,
405
            route,
406
            server_url,
407
            StatusCode::OK,
408
            StatusCode::BAD_REQUEST,
409
            VALIDATION_ERROR_STATUS,
410
            true,
411
        )
412
        .await
12✔
413
    }
414

415
    async fn test_extra_path_modified(
3✔
416
        test_executor: &TestExecutor,
417
        route: &str,
418
        server_url: &str,
419
    ) -> anyhow::Result<()> {
420
        do_test_extra_path(
421
            test_executor,
422
            route,
423
            server_url,
424
            StatusCode::OK,
425
            StatusCode::BAD_REQUEST,
426
            StatusCode::OK,
427
            false,
428
        )
429
        .await
12✔
430
    }
431

432
    async fn test_extra_path_validified(
3✔
433
        test_executor: &TestExecutor,
434
        route: &str,
435
        server_url: &str,
436
    ) -> anyhow::Result<()> {
437
        do_test_extra_path(
438
            test_executor,
439
            route,
440
            server_url,
441
            StatusCode::OK,
442
            StatusCode::BAD_REQUEST,
443
            VALIDATION_ERROR_STATUS,
444
            true,
445
        )
446
        .await
12✔
447
    }
448

449
    async fn do_test_extra_path(
3✔
450
        test_executor: &TestExecutor,
451
        route: &str,
452
        server_url: &str,
453
        expected_valid_status: StatusCode,
454
        expected_error_status: StatusCode,
455
        expected_invalid_status: StatusCode,
456
        should_check_json: bool,
457
    ) -> anyhow::Result<()> {
458
        let path_type_name = type_name::<Path<ParametersValidify>>();
6✔
459
        let valid_path_response = test_executor
15✔
460
            .client()
461
            .get(format!(
21✔
462
                "{}/{route}/{}/{}",
463
                server_url, VALID_PARAMETERS.v0, VALID_PARAMETERS.v1
6✔
464
            ))
465
            .send()
466
            .await?;
12✔
467
        assert_eq!(
3✔
468
            valid_path_response.status().as_u16(),
6✔
469
            expected_valid_status.as_u16(),
3✔
470
            "Valid '{}' test failed.",
471
            path_type_name
472
        );
473

474
        let error_path_response = test_executor
15✔
475
            .client()
476
            .get(format!("{}/{route}/not_i32/path", server_url))
9✔
477
            .send()
478
            .await?;
12✔
479
        assert_eq!(
6✔
480
            error_path_response.status().as_u16(),
6✔
481
            expected_error_status.as_u16(),
3✔
482
            "Error '{}' test failed: {}",
483
            path_type_name,
UNCOV
484
            error_path_response.text().await?
×
485
        );
486

487
        let invalid_path_response = test_executor
15✔
488
            .client()
489
            .get(format!(
21✔
490
                "{}/{route}/{}/{}",
491
                server_url, INVALID_PARAMETERS.v0, INVALID_PARAMETERS.v1
6✔
492
            ))
493
            .send()
494
            .await?;
12✔
495
        assert_eq!(
3✔
496
            invalid_path_response.status().as_u16(),
6✔
497
            expected_invalid_status.as_u16(),
3✔
498
            "Invalid '{}' test failed.",
499
            path_type_name
500
        );
501
        if should_check_json {
2✔
502
            #[cfg(feature = "into_json")]
503
            check_json(path_type_name, invalid_path_response).await;
2✔
504
        }
505
        println!("All {} tests passed.", path_type_name);
6✔
506
        Ok(())
3✔
507
    }
508

509
    test_extra_path(&test_executor, "path", &server_url).await?;
6✔
510
    test_extra_path_modified(&test_executor, "path_modified", &server_url).await?;
9✔
511
    test_extra_path_validified(&test_executor, "path_validified", &server_url).await?;
9✔
512
    test_extra_path(&test_executor, "path_validified_by_ref", &server_url).await?;
9✔
513

514
    // Validated
515
    test_executor
15✔
516
        .execute::<Query<ParametersValidify>>(Method::GET, route::QUERY)
3✔
517
        .await?;
12✔
518
    // Modified
519
    test_executor
15✔
520
        .execute_modified::<Query<ParametersValidify>>(Method::GET, route::QUERY_MODIFIED)
3✔
521
        .await?;
12✔
522
    // ValidifiedByRef
523
    test_executor
15✔
524
        .execute::<Query<ParametersValidify>>(Method::GET, route::QUERY_VALIDIFIED_BY_REF)
3✔
525
        .await?;
12✔
526
    // Validified
527
    test_executor
15✔
528
        .execute_validified::<Query<ParametersValidify>>(Method::GET, route::QUERY_VALIDIFIED)
3✔
529
        .await?;
12✔
530

531
    // Validated
532
    test_executor
15✔
533
        .execute::<Form<ParametersValidify>>(Method::POST, route::FORM)
3✔
534
        .await?;
12✔
535
    // Modified
536
    test_executor
15✔
537
        .execute_modified::<Form<ParametersValidify>>(Method::POST, route::FORM_MODIFIED)
3✔
538
        .await?;
12✔
539
    // ValidifiedByRef
540
    test_executor
15✔
541
        .execute::<Form<ParametersValidify>>(Method::POST, route::FORM_VALIDIFIED_BY_REF)
3✔
542
        .await?;
12✔
543
    // Validified
544
    test_executor
15✔
545
        .execute_validified::<Form<ParametersValidify>>(Method::POST, route::FORM_VALIDIFIED)
3✔
546
        .await?;
12✔
547

548
    // Validated
549
    test_executor
15✔
550
        .execute::<Json<ParametersValidify>>(Method::POST, route::JSON)
3✔
551
        .await?;
12✔
552
    // Modified
553
    test_executor
15✔
554
        .execute_modified::<Json<ParametersValidify>>(Method::POST, route::JSON_MODIFIED)
3✔
555
        .await?;
12✔
556
    // ValidifiedByRef
557
    test_executor
15✔
558
        .execute::<Json<ParametersValidify>>(Method::POST, route::JSON_VALIDIFIED_BY_REF)
3✔
559
        .await?;
12✔
560
    // Validified
561
    test_executor
15✔
562
        .execute_validified::<Json<ParametersValidify>>(Method::POST, route::JSON_VALIDIFIED)
3✔
563
        .await?;
12✔
564

565
    #[cfg(feature = "typed_header")]
566
    {
567
        use axum_extra::typed_header::TypedHeader;
568
        // Validated
569
        test_executor
15✔
570
            .execute::<TypedHeader<ParametersValidify>>(
571
                Method::POST,
3✔
572
                typed_header::route::TYPED_HEADER,
573
            )
574
            .await?;
12✔
575
        // Modified
576
        test_executor
15✔
577
            .execute_modified::<TypedHeader<ParametersValidify>>(
578
                Method::POST,
3✔
579
                typed_header::route::TYPED_HEADER_MODIFIED,
580
            )
581
            .await?;
12✔
582
        // ValidifiedByRef
583
        test_executor
15✔
584
            .execute::<TypedHeader<ParametersValidify>>(
585
                Method::POST,
3✔
586
                typed_header::route::TYPED_HEADER_VALIDIFIED_BY_REF,
587
            )
588
            .await?;
12✔
589
    }
590

591
    #[cfg(feature = "typed_multipart")]
592
    {
593
        use axum_typed_multipart::{BaseMultipart, TypedMultipart, TypedMultipartError};
594

595
        // Validated
596
        test_executor
15✔
597
            .execute::<BaseMultipart<ParametersValidify, TypedMultipartError>>(
598
                Method::POST,
3✔
599
                typed_multipart::route::BASE_MULTIPART,
600
            )
601
            .await?;
12✔
602
        // Modified
603
        test_executor
15✔
604
            .execute_modified::<BaseMultipart<ParametersValidify, TypedMultipartError>>(
605
                Method::POST,
3✔
606
                typed_multipart::route::BASE_MULTIPART_MODIFIED,
607
            )
608
            .await?;
12✔
609
        // ValidifiedByRef
610
        test_executor
15✔
611
            .execute::<BaseMultipart<ParametersValidify, TypedMultipartError>>(
612
                Method::POST,
3✔
613
                typed_multipart::route::BASE_MULTIPART_VALIDIFIED_BY_REF,
614
            )
615
            .await?;
12✔
616

617
        // Validated
618
        test_executor
15✔
619
            .execute::<TypedMultipart<ParametersValidify>>(
620
                Method::POST,
3✔
621
                typed_multipart::route::TYPED_MULTIPART,
622
            )
623
            .await?;
12✔
624
        // Modified
625
        test_executor
15✔
626
            .execute_modified::<TypedMultipart<ParametersValidify>>(
627
                Method::POST,
3✔
628
                typed_multipart::route::TYPED_MULTIPART_MODIFIED,
629
            )
630
            .await?;
12✔
631
        // ValidifiedByRef
632
        test_executor
15✔
633
            .execute::<TypedMultipart<ParametersValidify>>(
634
                Method::POST,
3✔
635
                typed_multipart::route::TYPED_MULTIPART_VALIDIFIED_BY_REF,
636
            )
637
            .await?;
12✔
638
    }
639

640
    #[cfg(feature = "extra")]
641
    {
642
        use axum_extra::extract::{Cached, WithRejection};
643
        use extra::{
644
            ParametersRejection, ValidifyWithRejectionRejection, WithRejectionValidifyRejection,
645
        };
646
        // Validated
647
        test_executor
15✔
648
            .execute::<Cached<ParametersValidify>>(Method::POST, extra::route::CACHED)
3✔
649
            .await?;
12✔
650
        // Modified
651
        test_executor
15✔
652
            .execute_modified::<Cached<ParametersValidify>>(
653
                Method::POST,
3✔
654
                extra::route::CACHED_MODIFIED,
655
            )
656
            .await?;
12✔
657
        // ValidifiedByRef
658
        test_executor
15✔
659
            .execute::<Cached<ParametersValidify>>(
660
                Method::POST,
3✔
661
                extra::route::CACHED_VALIDIFIED_BY_REF,
662
            )
663
            .await?;
12✔
664

665
        // Validated
666
        test_executor
15✔
667
            .execute::<WithRejection<ParametersValidify, ValidifyWithRejectionRejection>>(
668
                Method::POST,
3✔
669
                extra::route::WITH_REJECTION,
670
            )
671
            .await?;
12✔
672
        // Modified
673
        test_executor
15✔
674
            .execute_modified::<WithRejection<ParametersValidify, ValidifyWithRejectionRejection>>(
675
                Method::POST,
3✔
676
                extra::route::WITH_REJECTION_MODIFIED,
677
            )
678
            .await?;
12✔
679
        // ValidifiedByRef
680
        test_executor
15✔
681
            .execute::<WithRejection<ParametersValidify, ValidifyWithRejectionRejection>>(
682
                Method::POST,
3✔
683
                extra::route::WITH_REJECTION_VALIDIFIED_BY_REF,
684
            )
685
            .await?;
12✔
686

687
        // Validated
688
        test_executor
15✔
689
            .execute::<WithRejection<
690
                Validated<ParametersValidify>,
691
                WithRejectionValidifyRejection<ParametersRejection>,
692
            >>(Method::POST, extra::route::WITH_REJECTION_VALIDIFY)
3✔
693
            .await?;
12✔
694
        // Modified
695
        test_executor
15✔
696
            .execute_modified::<WithRejection<
697
                Modified<ParametersValidify>,
698
                ValidifyWithRejectionRejection,
699
            >>(Method::POST, extra::route::WITH_REJECTION_VALIDIFY_MODIFIED)
3✔
700
            .await?;
12✔
701
        // ValidifiedByRef
702
        test_executor
15✔
703
            .execute::<WithRejection<
704
                ValidifiedByRef<ParametersValidify>,
705
                WithRejectionValidifyRejection<ParametersRejection>,
706
            >>(
707
                Method::POST,
3✔
708
                extra::route::WITH_REJECTION_VALIDIFY_VALIDIFIED_BY_REF,
709
            )
710
            .await?;
12✔
711
    }
712

713
    #[cfg(feature = "extra_typed_path")]
714
    {
715
        async fn test_extra_typed_path(
3✔
716
            test_executor: &TestExecutor,
717
            route: &str,
718
            server_url: &str,
719
        ) -> anyhow::Result<()> {
720
            do_test_extra_typed_path(
721
                test_executor,
722
                route,
723
                server_url,
724
                StatusCode::OK,
725
                StatusCode::BAD_REQUEST,
726
                VALIDATION_ERROR_STATUS,
727
                true,
728
            )
729
            .await
12✔
730
        }
731

732
        async fn test_extra_typed_path_modified(
3✔
733
            test_executor: &TestExecutor,
734
            route: &str,
735
            server_url: &str,
736
        ) -> anyhow::Result<()> {
737
            do_test_extra_typed_path(
738
                test_executor,
739
                route,
740
                server_url,
741
                StatusCode::OK,
742
                StatusCode::BAD_REQUEST,
743
                StatusCode::OK,
744
                false,
745
            )
746
            .await
12✔
747
        }
748

749
        async fn do_test_extra_typed_path(
3✔
750
            test_executor: &TestExecutor,
751
            route: &str,
752
            server_url: &str,
753
            expected_valid_status: StatusCode,
754
            expected_error_status: StatusCode,
755
            expected_invalid_status: StatusCode,
756
            should_check_json: bool,
757
        ) -> anyhow::Result<()> {
758
            let extra_typed_path_type_name = "T: TypedPath";
3✔
759
            let valid_extra_typed_path_response = test_executor
15✔
760
                .client()
761
                .get(format!(
21✔
762
                    "{}/{route}/{}/{}",
763
                    server_url, VALID_PARAMETERS.v0, VALID_PARAMETERS.v1
6✔
764
                ))
765
                .send()
766
                .await?;
12✔
767
            assert_eq!(
3✔
768
                valid_extra_typed_path_response.status().as_u16(),
6✔
769
                expected_valid_status.as_u16(),
3✔
770
                "Validified '{}' test failed.",
771
                extra_typed_path_type_name
772
            );
773

774
            let error_extra_typed_path_response = test_executor
15✔
775
                .client()
776
                .get(format!("{}/{route}/not_i32/path", server_url))
9✔
777
                .send()
778
                .await?;
12✔
779
            assert_eq!(
3✔
780
                error_extra_typed_path_response.status().as_u16(),
6✔
781
                expected_error_status.as_u16(),
3✔
782
                "Error '{}' test failed.",
783
                extra_typed_path_type_name
784
            );
785

786
            let invalid_extra_typed_path_response = test_executor
15✔
787
                .client()
788
                .get(format!(
21✔
789
                    "{}/{route}/{}/{}",
790
                    server_url, INVALID_PARAMETERS.v0, INVALID_PARAMETERS.v1
6✔
791
                ))
792
                .send()
793
                .await?;
12✔
794
            assert_eq!(
3✔
795
                invalid_extra_typed_path_response.status().as_u16(),
6✔
796
                expected_invalid_status.as_u16(),
3✔
797
                "Invalid '{}' test failed.",
798
                extra_typed_path_type_name
799
            );
800

801
            if should_check_json {
2✔
802
                #[cfg(feature = "into_json")]
803
                check_json(
804
                    extra_typed_path_type_name,
2✔
805
                    invalid_extra_typed_path_response,
2✔
806
                )
807
                .await;
4✔
808
            }
809
            println!("All {} tests passed.", extra_typed_path_type_name);
6✔
810
            Ok(())
3✔
811
        }
812

813
        test_extra_typed_path(&test_executor, "extra_typed_path", &server_url).await?;
9✔
814
        test_extra_typed_path_modified(&test_executor, "extra_typed_path_modified", &server_url)
15✔
815
            .await?;
12✔
816
        test_extra_typed_path(
817
            &test_executor,
3✔
818
            "extra_typed_path_validified_by_ref",
819
            &server_url,
3✔
820
        )
821
        .await?;
12✔
822
    }
823

824
    #[cfg(feature = "extra_query")]
825
    {
826
        use axum_extra::extract::Query;
827
        // Validated
828
        test_executor
15✔
829
            .execute::<Query<ParametersValidify>>(Method::POST, extra_query::route::EXTRA_QUERY)
3✔
830
            .await?;
12✔
831
        // Modified
832
        test_executor
15✔
833
            .execute_modified::<Query<ParametersValidify>>(
834
                Method::POST,
3✔
835
                extra_query::route::EXTRA_QUERY_MODIFIED,
836
            )
837
            .await?;
12✔
838
        // Validified
839
        test_executor
15✔
840
            .execute_validified::<Query<ParametersValidify>>(
841
                Method::POST,
3✔
842
                extra_query::route::EXTRA_QUERY_VALIDIFIED,
843
            )
844
            .await?;
12✔
845
        // ValidifiedByRef
846
        test_executor
15✔
847
            .execute::<Query<ParametersValidify>>(
848
                Method::POST,
3✔
849
                extra_query::route::EXTRA_QUERY_VALIDIFIED_BY_REF,
850
            )
851
            .await?;
12✔
852
    }
853

854
    #[cfg(feature = "extra_form")]
855
    {
856
        use axum_extra::extract::Form;
857
        // Validated
858
        test_executor
15✔
859
            .execute::<Form<ParametersValidify>>(Method::POST, extra_form::route::EXTRA_FORM)
3✔
860
            .await?;
12✔
861
        // Modified
862
        test_executor
15✔
863
            .execute_modified::<Form<ParametersValidify>>(
864
                Method::POST,
3✔
865
                extra_form::route::EXTRA_FORM_MODIFIED,
866
            )
867
            .await?;
12✔
868
        // Validified
869
        test_executor
15✔
870
            .execute_validified::<Form<ParametersValidify>>(
871
                Method::POST,
3✔
872
                extra_form::route::EXTRA_FORM_VALIDIFED,
873
            )
874
            .await?;
12✔
875
        // ValidifiedByRef
876
        test_executor
15✔
877
            .execute::<Form<ParametersValidify>>(
878
                Method::POST,
3✔
879
                extra_form::route::EXTRA_FORM_VALIDIFED_BY_REF,
880
            )
881
            .await?;
12✔
882
    }
883

884
    #[cfg(feature = "extra_protobuf")]
885
    {
886
        use axum_extra::protobuf::Protobuf;
887
        // Validated
888
        test_executor
15✔
889
            .execute::<Protobuf<ParametersValidifyWithoutPayload>>(
890
                Method::POST,
3✔
891
                extra_protobuf::route::EXTRA_PROTOBUF,
892
            )
893
            .await?;
12✔
894
        // Modified
895
        test_executor
15✔
896
            .execute_modified::<Protobuf<ParametersValidifyWithoutPayload>>(
897
                Method::POST,
3✔
898
                extra_protobuf::route::EXTRA_PROTOBUF_MODIFIED,
899
            )
900
            .await?;
12✔
901
        // ValidifiedByRef
902
        test_executor
15✔
903
            .execute::<Protobuf<ParametersValidifyWithoutPayload>>(
904
                Method::POST,
3✔
905
                extra_protobuf::route::EXTRA_PROTOBUF_VALIDIFIED_BY_REF,
906
            )
907
            .await?;
12✔
908
    }
909

910
    #[cfg(feature = "yaml")]
911
    {
912
        use axum_serde::Yaml;
913

914
        // Validated
915
        test_executor
15✔
916
            .execute::<Yaml<ParametersValidify>>(Method::POST, yaml::route::YAML)
3✔
917
            .await?;
12✔
918
        // Modified
919
        test_executor
15✔
920
            .execute_modified::<Yaml<ParametersValidify>>(Method::POST, yaml::route::YAML_MODIFIED)
3✔
921
            .await?;
12✔
922
        // Validified
923
        test_executor
15✔
924
            .execute_validified::<Yaml<ParametersValidify>>(
925
                Method::POST,
3✔
926
                yaml::route::YAML_VALIDIFIED,
927
            )
928
            .await?;
12✔
929
        // ValidifiedByRef
930
        test_executor
15✔
931
            .execute::<Yaml<ParametersValidify>>(Method::POST, yaml::route::YAML_VALIDIFIED_BY_REF)
3✔
932
            .await?;
12✔
933
    }
934

935
    #[cfg(feature = "msgpack")]
936
    {
937
        use axum_serde::{MsgPack, MsgPackRaw};
938
        // Validated
939
        test_executor
15✔
940
            .execute::<MsgPack<ParametersValidify>>(Method::POST, msgpack::route::MSGPACK)
3✔
941
            .await?;
12✔
942
        // Modified
943
        test_executor
15✔
944
            .execute_modified::<MsgPack<ParametersValidify>>(
945
                Method::POST,
3✔
946
                msgpack::route::MSGPACK_MODIFIED,
947
            )
948
            .await?;
12✔
949
        // Validified
950
        test_executor
15✔
951
            .execute_validified::<MsgPack<ParametersValidify>>(
952
                Method::POST,
3✔
953
                msgpack::route::MSGPACK_VALIDIFIED,
954
            )
955
            .await?;
12✔
956
        // ValidifiedByRef
957
        test_executor
15✔
958
            .execute::<MsgPack<ParametersValidify>>(
959
                Method::POST,
3✔
960
                msgpack::route::MSGPACK_VALIDIFIED_BY_REF,
961
            )
962
            .await?;
12✔
963

964
        //
965
        test_executor
15✔
966
            .execute::<MsgPackRaw<ParametersValidify>>(Method::POST, msgpack::route::MSGPACK_RAW)
3✔
967
            .await?;
12✔
968
        //
969
        test_executor
15✔
970
            .execute_modified::<MsgPackRaw<ParametersValidify>>(
971
                Method::POST,
3✔
972
                msgpack::route::MSGPACK_RAW_MODIFIED,
973
            )
974
            .await?;
12✔
975
        //
976
        test_executor
15✔
977
            .execute_validified::<MsgPackRaw<ParametersValidify>>(
978
                Method::POST,
3✔
979
                msgpack::route::MSGPACK_RAW_VALIDIFIED,
980
            )
981
            .await?;
12✔
982
        //
983
        test_executor
15✔
984
            .execute::<MsgPackRaw<ParametersValidify>>(
985
                Method::POST,
3✔
986
                msgpack::route::MSGPACK_RAW_VALIDIFIED_BY_REF,
987
            )
988
            .await?;
12✔
989
    }
990

991
    #[cfg(feature = "xml")]
992
    {
993
        use axum_serde::Xml;
994

995
        // Validated
996
        test_executor
15✔
997
            .execute::<Xml<ParametersValidify>>(Method::POST, xml::route::XML)
3✔
998
            .await?;
12✔
999
        // Modified
1000
        test_executor
15✔
1001
            .execute_modified::<Xml<ParametersValidify>>(Method::POST, xml::route::XML_MODIFIED)
3✔
1002
            .await?;
12✔
1003
        // Validified
1004
        test_executor
15✔
1005
            .execute_validified::<Xml<ParametersValidify>>(Method::POST, xml::route::XML_VALIDIFIED)
3✔
1006
            .await?;
12✔
1007
        // ValidifiedByRef
1008
        test_executor
15✔
1009
            .execute::<Xml<ParametersValidify>>(Method::POST, xml::route::XML_VALIDIFIED_BY_REF)
3✔
1010
            .await?;
12✔
1011
    }
1012

1013
    #[cfg(feature = "toml")]
1014
    {
1015
        use axum_serde::Toml;
1016

1017
        // Validated
1018
        test_executor
15✔
1019
            .execute::<Toml<ParametersValidify>>(Method::POST, toml::route::TOML)
3✔
1020
            .await?;
12✔
1021
        // Modified
1022
        test_executor
15✔
1023
            .execute_modified::<Toml<ParametersValidify>>(Method::POST, toml::route::TOML_MODIFIED)
3✔
1024
            .await?;
12✔
1025
        // Validified
1026
        test_executor
15✔
1027
            .execute_validified::<Toml<ParametersValidify>>(
1028
                Method::POST,
3✔
1029
                toml::route::TOML_VALIDIFIED,
1030
            )
1031
            .await?;
12✔
1032
        // ValidifiedByRef
1033
        test_executor
15✔
1034
            .execute::<Toml<ParametersValidify>>(Method::POST, toml::route::TOML_VALIDIFIED_BY_REF)
3✔
1035
            .await?;
12✔
1036
    }
1037

1038
    #[cfg(feature = "sonic")]
1039
    {
1040
        use axum_serde::Sonic;
1041

1042
        // Validated
1043
        test_executor
15✔
1044
            .execute::<Sonic<ParametersValidify>>(Method::POST, sonic::route::SONIC)
3✔
1045
            .await?;
12✔
1046
        // Modified
1047
        test_executor
15✔
1048
            .execute_modified::<Sonic<ParametersValidify>>(
1049
                Method::POST,
3✔
1050
                sonic::route::SONIC_MODIFIED,
1051
            )
1052
            .await?;
12✔
1053
        // Validified
1054
        test_executor
15✔
1055
            .execute_validified::<Sonic<ParametersValidify>>(
1056
                Method::POST,
3✔
1057
                sonic::route::SONIC_VALIDIFIED,
1058
            )
1059
            .await?;
12✔
1060
        // ValidifiedByRef
1061
        test_executor
15✔
1062
            .execute::<Sonic<ParametersValidify>>(
1063
                Method::POST,
3✔
1064
                sonic::route::SONIC_VALIDIFIED_BY_REF,
1065
            )
1066
            .await?;
12✔
1067
    }
1068

1069
    Ok(())
3✔
1070
}
1071

1072
#[derive(Debug, Clone)]
1073
pub struct TestExecutor {
1074
    client: reqwest::Client,
1075
    server_url: Url,
1076
}
1077

1078
impl From<Url> for TestExecutor {
1079
    fn from(server_url: Url) -> Self {
3✔
1080
        Self {
1081
            client: Default::default(),
3✔
1082
            server_url,
1083
        }
1084
    }
1085
}
1086

1087
impl TestExecutor {
1088
    /// Execute all tests
1089
    pub async fn execute<T: ValidTest>(&self, method: Method, route: &str) -> anyhow::Result<()> {
285✔
1090
        self.do_execute::<T>(
171✔
UNCOV
1091
            method,
×
UNCOV
1092
            route,
×
UNCOV
1093
            StatusCode::OK,
×
UNCOV
1094
            T::ERROR_STATUS_CODE,
×
UNCOV
1095
            T::INVALID_STATUS_CODE,
×
1096
            true,
1097
        )
1098
        .await
228✔
1099
    }
1100

1101
    /// Execute all tests for `Modified` without validation
1102
    pub async fn execute_modified<T: ValidTest>(
54✔
1103
        &self,
1104
        method: Method,
1105
        route: &str,
1106
    ) -> anyhow::Result<()> {
1107
        self.do_execute::<T>(
162✔
UNCOV
1108
            method,
×
UNCOV
1109
            route,
×
UNCOV
1110
            StatusCode::OK,
×
UNCOV
1111
            T::ERROR_STATUS_CODE,
×
1112
            StatusCode::OK,
×
1113
            false,
1114
        )
1115
        .await
216✔
1116
    }
1117

1118
    /// Execute all tests for `Modified` without validation
1119
    pub async fn execute_validified<T: ValidTest>(
33✔
1120
        &self,
1121
        method: Method,
1122
        route: &str,
1123
    ) -> anyhow::Result<()> {
1124
        self.do_execute::<T>(
99✔
UNCOV
1125
            method,
×
UNCOV
1126
            route,
×
UNCOV
1127
            StatusCode::OK,
×
UNCOV
1128
            T::INVALID_STATUS_CODE,
×
UNCOV
1129
            T::INVALID_STATUS_CODE,
×
1130
            false,
1131
        )
1132
        .await
132✔
1133
    }
1134

1135
    async fn do_execute<T: ValidTest>(
60✔
1136
        &self,
1137
        method: Method,
1138
        route: &str,
1139
        expected_valid_status: StatusCode,
1140
        expected_error_status: StatusCode,
1141
        expected_invalid_status: StatusCode,
1142
        should_check_json: bool,
1143
    ) -> anyhow::Result<()> {
UNCOV
1144
        let url = {
×
1145
            let mut url_builder = self.server_url.clone();
60✔
1146
            url_builder.set_path(route);
60✔
1147
            url_builder
60✔
1148
        };
1149

1150
        let type_name = type_name::<T>();
120✔
1151

1152
        let valid_builder = self.client.request(method.clone(), url.clone());
120✔
1153
        let valid_response = T::set_valid_request(valid_builder).send().await?;
180✔
1154
        assert_eq!(
120✔
1155
            valid_response.status().as_u16(),
120✔
1156
            expected_valid_status.as_u16(),
60✔
1157
            "Validified '{}' test failed: {}.",
UNCOV
1158
            type_name,
×
UNCOV
1159
            valid_response.text().await?
×
1160
        );
1161

1162
        let error_builder = self.client.request(method.clone(), url.clone());
120✔
1163
        let error_response = T::set_error_request(error_builder).send().await?;
180✔
1164
        assert_eq!(
120✔
1165
            error_response.status().as_u16(),
120✔
1166
            expected_error_status.as_u16(),
60✔
1167
            "Error '{}' test failed: {}.",
UNCOV
1168
            type_name,
×
UNCOV
1169
            error_response.text().await?
×
1170
        );
1171

1172
        let invalid_builder = self.client.request(method, url);
60✔
1173
        let invalid_response = T::set_invalid_request(invalid_builder).send().await?;
180✔
1174
        assert_eq!(
120✔
1175
            invalid_response.status().as_u16(),
120✔
1176
            expected_invalid_status.as_u16(),
60✔
1177
            "Invalid '{}' test failed: {}.",
UNCOV
1178
            type_name,
×
UNCOV
1179
            invalid_response.text().await?
×
1180
        );
1181
        if should_check_json {
40✔
UNCOV
1182
            #[cfg(feature = "into_json")]
×
1183
            if T::JSON_SERIALIZABLE {
38✔
1184
                check_json(type_name, invalid_response).await;
34✔
1185
            }
1186
        }
1187

1188
        println!("All '{}' tests passed.", type_name);
120✔
1189
        Ok(())
60✔
1190
    }
1191

1192
    pub fn client(&self) -> &reqwest::Client {
3✔
1193
        &self.client
3✔
1194
    }
1195
}
1196

1197
/// Check if the response is a json response
1198
#[cfg(feature = "into_json")]
1199
pub async fn check_json(type_name: &'static str, response: reqwest::Response) {
12✔
1200
    assert_eq!(
4✔
1201
        response.headers()[reqwest::header::CONTENT_TYPE],
4✔
1202
        reqwest::header::HeaderValue::from_static(mime::APPLICATION_JSON.as_ref()),
2✔
1203
        "'{}' rejection into json test failed",
1204
        type_name
1205
    );
1206
    assert!(response.json::<serde_json::Value>().await.is_ok());
2✔
1207
}
1208

1209
mod route {
1210
    pub const PATH: &str = "/path/:v0/:v1";
1211
    pub const PATH_MODIFIED: &str = "/path_modified/:v0/:v1";
1212
    pub const PATH_VALIDIFIED: &str = "/path_validified/:v0/:v1";
1213
    pub const PATH_VALIDIFIED_BY_REF: &str = "/path_validified_by_ref/:v0/:v1";
1214
    pub const QUERY: &str = "/query";
1215
    pub const QUERY_MODIFIED: &str = "/query_modified/:v0/:v1";
1216

1217
    pub const QUERY_VALIDIFIED: &str = "/query_validified/:v0/:v1";
1218
    pub const QUERY_VALIDIFIED_BY_REF: &str = "/query_validified_by_ref/:v0/:v1";
1219
    pub const FORM: &str = "/form";
1220
    pub const FORM_MODIFIED: &str = "/form_modified/:v0/:v1";
1221
    pub const FORM_VALIDIFIED: &str = "/form_validified/:v0/:v1";
1222
    pub const FORM_VALIDIFIED_BY_REF: &str = "/form_validified_by_ref/:v0/:v1";
1223
    pub const JSON: &str = "/json";
1224
    pub const JSON_MODIFIED: &str = "/json_modified/:v0/:v1";
1225
    pub const JSON_VALIDIFIED: &str = "/json_validified/:v0/:v1";
1226
    pub const JSON_VALIDIFIED_BY_REF: &str = "/json_validified_by_ref/:v0/:v1";
1227
}
1228

1229
async fn extract_path(
3✔
1230
    Validated(Path(parameters)): Validated<Path<ParametersValidify>>,
1231
) -> StatusCode {
1232
    check_validated(&parameters)
3✔
1233
}
1234

1235
async fn extract_path_modified(
3✔
1236
    Modified(Path(parameters)): Modified<Path<ParametersValidify>>,
1237
) -> StatusCode {
1238
    check_modified(&parameters)
3✔
1239
}
1240

1241
async fn extract_path_validified(
3✔
1242
    Validified(Path(parameters)): Validified<Path<ParametersValidify>>,
1243
) -> StatusCode {
1244
    check_validified(&parameters)
3✔
1245
}
1246

1247
async fn extract_path_validified_by_ref(
3✔
1248
    ValidifiedByRef(Path(parameters)): ValidifiedByRef<Path<ParametersValidify>>,
1249
) -> StatusCode {
1250
    check_validified(&parameters)
3✔
1251
}
1252

1253
async fn extract_query(
3✔
1254
    Validated(Query(parameters)): Validated<Query<ParametersValidify>>,
1255
) -> StatusCode {
1256
    check_validated(&parameters)
3✔
1257
}
1258

1259
async fn extract_query_modified(
3✔
1260
    Modified(Query(parameters)): Modified<Query<ParametersValidify>>,
1261
) -> StatusCode {
1262
    check_modified(&parameters)
3✔
1263
}
1264

1265
async fn extract_query_validified(
3✔
1266
    Validified(Query(parameters)): Validified<Query<ParametersValidify>>,
1267
) -> StatusCode {
1268
    check_validified(&parameters)
3✔
1269
}
1270

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

1277
async fn extract_form(
3✔
1278
    Validated(Form(parameters)): Validated<Form<ParametersValidify>>,
1279
) -> StatusCode {
1280
    check_validated(&parameters)
3✔
1281
}
1282

1283
async fn extract_form_modified(
3✔
1284
    Modified(Form(parameters)): Modified<Form<ParametersValidify>>,
1285
) -> StatusCode {
1286
    check_modified(&parameters)
3✔
1287
}
1288

1289
async fn extract_form_validified(
3✔
1290
    Validified(Form(parameters)): Validified<Form<ParametersValidify>>,
1291
) -> StatusCode {
1292
    check_validified(&parameters)
3✔
1293
}
1294

1295
async fn extract_form_validified_by_ref(
3✔
1296
    ValidifiedByRef(Form(parameters)): ValidifiedByRef<Form<ParametersValidify>>,
1297
) -> StatusCode {
1298
    check_validified(&parameters)
3✔
1299
}
1300

1301
async fn extract_json(
3✔
1302
    Validated(Json(parameters)): Validated<Json<ParametersValidify>>,
1303
) -> StatusCode {
1304
    check_validated(&parameters)
3✔
1305
}
1306

1307
async fn extract_json_modified(
3✔
1308
    Modified(Json(parameters)): Modified<Json<ParametersValidify>>,
1309
) -> StatusCode {
1310
    check_modified(&parameters)
3✔
1311
}
1312

1313
async fn extract_json_validified(
3✔
1314
    Validified(Json(parameters)): Validified<Json<ParametersValidify>>,
1315
) -> StatusCode {
1316
    check_validified(&parameters)
3✔
1317
}
1318

1319
async fn extract_json_validified_by_ref(
3✔
1320
    ValidifiedByRef(Json(parameters)): ValidifiedByRef<Json<ParametersValidify>>,
1321
) -> StatusCode {
1322
    check_validified(&parameters)
3✔
1323
}
1324

1325
fn check_validated<V: Validate>(validate: &V) -> StatusCode {
12✔
1326
    // The `Validified` extractor has validated the `parameters` once,
1327
    // it should have returned `400 BAD REQUEST` if the `parameters` were invalid,
1328
    // Let's validate them again to check if the `Validated` extractor works well.
1329
    // If it works properly, this function will never return `500 INTERNAL SERVER ERROR`
1330
    match validate.validate() {
12✔
1331
        Ok(_) => StatusCode::OK,
12✔
UNCOV
1332
        Err(e) => {
×
UNCOV
1333
            eprintln!("Data is unvalidated: {e}");
×
UNCOV
1334
            StatusCode::INTERNAL_SERVER_ERROR
×
1335
        }
1336
    }
1337
}
1338

1339
fn check_modified<M: IsModified>(modify: &M) -> StatusCode {
12✔
1340
    if modify.modified() {
12✔
1341
        StatusCode::OK
12✔
1342
    } else {
UNCOV
1343
        StatusCode::INTERNAL_SERVER_ERROR
×
1344
    }
1345
}
1346

1347
fn check_validified<D: IsModified + Validate>(data: &D) -> StatusCode {
9✔
1348
    let status = check_modified(data);
9✔
1349
    if status != StatusCode::OK {
9✔
UNCOV
1350
        return status;
×
1351
    }
1352

1353
    check_validated(data)
9✔
1354
}
1355

1356
#[cfg(feature = "typed_header")]
1357
mod typed_header {
1358
    pub(crate) mod route {
1359
        pub const TYPED_HEADER: &str = "/typed_header";
1360
        pub const TYPED_HEADER_MODIFIED: &str = "/typed_header_modified";
1361
        pub const TYPED_HEADER_VALIDIFIED_BY_REF: &str = "/typed_header_validified_be_ref";
1362
    }
1363

1364
    use super::{check_modified, check_validated, check_validified, ParametersValidify};
1365
    use crate::{Modified, Validated, ValidifiedByRef};
1366
    use axum::http::StatusCode;
1367
    use axum_extra::headers::{Error, Header, HeaderName, HeaderValue};
1368
    use axum_extra::typed_header::TypedHeader;
1369

1370
    pub static AXUM_VALID_PARAMETERS: HeaderName = HeaderName::from_static("axum-valid-parameters");
1371

1372
    pub(super) async fn extract_typed_header(
3✔
1373
        Validated(TypedHeader(parameters)): Validated<TypedHeader<ParametersValidify>>,
1374
    ) -> StatusCode {
1375
        check_validated(&parameters)
3✔
1376
    }
1377

1378
    pub(super) async fn extract_typed_header_modified(
3✔
1379
        Modified(TypedHeader(parameters)): Modified<TypedHeader<ParametersValidify>>,
1380
    ) -> StatusCode {
1381
        check_modified(&parameters)
3✔
1382
    }
1383

1384
    pub(super) async fn extract_typed_header_validified_by_ref(
3✔
1385
        ValidifiedByRef(TypedHeader(parameters)): ValidifiedByRef<TypedHeader<ParametersValidify>>,
1386
    ) -> StatusCode {
1387
        check_validified(&parameters)
3✔
1388
    }
1389

1390
    impl Header for ParametersValidify {
1391
        fn name() -> &'static HeaderName {
1392
            &AXUM_VALID_PARAMETERS
1393
        }
1394

1395
        fn decode<'i, I>(values: &mut I) -> Result<Self, Error>
6✔
1396
        where
1397
            Self: Sized,
1398
            I: Iterator<Item = &'i HeaderValue>,
1399
        {
1400
            let value = values.next().ok_or_else(Error::invalid)?;
9✔
1401
            let src = std::str::from_utf8(value.as_bytes()).map_err(|_| Error::invalid())?;
12✔
1402
            let split = src.split(',').collect::<Vec<_>>();
6✔
1403
            match split.as_slice() {
6✔
1404
                [v0, v1] => Ok(ParametersValidify {
18✔
1405
                    v0: v0.parse().map_err(|_| Error::invalid())?,
18✔
1406
                    v1: v1.to_string(),
6✔
1407
                }),
UNCOV
1408
                _ => Err(Error::invalid()),
×
1409
            }
1410
        }
1411

1412
        fn encode<E: Extend<HeaderValue>>(&self, values: &mut E) {
3✔
1413
            let v0 = self.v0.to_string();
3✔
1414
            let mut vec = Vec::with_capacity(v0.len() + 1 + self.v1.len());
6✔
1415
            vec.extend_from_slice(v0.as_bytes());
6✔
1416
            vec.push(b',');
3✔
1417
            vec.extend_from_slice(self.v1.as_bytes());
3✔
1418
            let value = HeaderValue::from_bytes(&vec).expect("Failed to build header");
3✔
1419
            values.extend(::std::iter::once(value));
3✔
1420
        }
1421
    }
1422

1423
    #[test]
1424
    fn parameter_is_header() -> anyhow::Result<()> {
1425
        let parameter = ParametersValidify {
1426
            v0: 123456,
1427
            v1: "111111".to_string(),
1428
        };
1429
        let mut vec = Vec::new();
1430
        parameter.encode(&mut vec);
1431
        let mut iter = vec.iter();
1432
        assert_eq!(parameter, ParametersValidify::decode(&mut iter)?);
1433
        Ok(())
1434
    }
1435
}
1436

1437
#[cfg(feature = "typed_multipart")]
1438
mod typed_multipart {
1439
    use super::{
1440
        check_modified, check_validated, check_validified, ParametersValidify,
1441
        ParametersValidifyWithoutPayload,
1442
    };
1443
    use crate::{Modified, Validated, ValidifiedByRef};
1444
    use axum::http::StatusCode;
1445
    use axum_typed_multipart::{BaseMultipart, TypedMultipart, TypedMultipartError};
1446

1447
    pub mod route {
1448
        pub const TYPED_MULTIPART: &str = "/typed_multipart";
1449
        pub const TYPED_MULTIPART_MODIFIED: &str = "/typed_multipart_modified";
1450
        pub const TYPED_MULTIPART_VALIDIFIED_BY_REF: &str = "/typed_multipart_validified_by_ref";
1451

1452
        pub const BASE_MULTIPART: &str = "/base_multipart";
1453
        pub const BASE_MULTIPART_MODIFIED: &str = "/base_multipart_modified";
1454
        pub const BASE_MULTIPART_VALIDIFIED_BY_REF: &str = "/base_multipart_validified_by_ref";
1455
    }
1456

1457
    impl From<&ParametersValidify> for reqwest::multipart::Form {
1458
        fn from(value: &ParametersValidify) -> Self {
3✔
1459
            reqwest::multipart::Form::new()
9✔
1460
                .text("v0", value.v0.to_string())
6✔
1461
                .text("v1", value.v1.clone())
6✔
1462
        }
1463
    }
1464

1465
    pub(super) async fn extract_typed_multipart(
3✔
1466
        Validated(TypedMultipart(parameters)): Validated<
1467
            TypedMultipart<ParametersValidifyWithoutPayload>,
1468
        >,
1469
    ) -> StatusCode {
1470
        check_validated(&parameters)
3✔
1471
    }
1472

1473
    pub(super) async fn extract_typed_multipart_modified(
3✔
1474
        Modified(TypedMultipart(parameters)): Modified<
1475
            TypedMultipart<ParametersValidifyWithoutPayload>,
1476
        >,
1477
    ) -> StatusCode {
1478
        check_modified(&parameters)
3✔
1479
    }
1480

1481
    pub(super) async fn extract_typed_multipart_validified_by_ref(
3✔
1482
        ValidifiedByRef(TypedMultipart(parameters)): ValidifiedByRef<
1483
            TypedMultipart<ParametersValidifyWithoutPayload>,
1484
        >,
1485
    ) -> StatusCode {
1486
        check_validified(&parameters)
3✔
1487
    }
1488

1489
    pub(super) async fn extract_base_multipart(
3✔
1490
        Validated(BaseMultipart { data, .. }): Validated<
1491
            BaseMultipart<ParametersValidifyWithoutPayload, TypedMultipartError>,
1492
        >,
1493
    ) -> StatusCode {
1494
        check_validated(&data)
3✔
1495
    }
1496

1497
    pub(super) async fn extract_base_multipart_modified(
3✔
1498
        Modified(BaseMultipart { data, .. }): Modified<
1499
            BaseMultipart<ParametersValidifyWithoutPayload, TypedMultipartError>,
1500
        >,
1501
    ) -> StatusCode {
1502
        check_modified(&data)
3✔
1503
    }
1504

1505
    pub(super) async fn extract_base_multipart_validified_by_ref(
3✔
1506
        ValidifiedByRef(BaseMultipart { data, .. }): ValidifiedByRef<
1507
            BaseMultipart<ParametersValidifyWithoutPayload, TypedMultipartError>,
1508
        >,
1509
    ) -> StatusCode {
1510
        check_validified(&data)
3✔
1511
    }
1512
}
1513

1514
#[cfg(feature = "extra")]
1515
mod extra {
1516
    use super::{check_modified, check_validated, check_validified, ParametersValidify};
1517
    use crate::tests::{Rejection, ValidTest, ValidTestParameter};
1518
    use crate::{HasModify, Modified, Validated, ValidifiedByRef, ValidifyRejection};
1519
    use axum::extract::FromRequestParts;
1520
    use axum::http::request::Parts;
1521
    use axum::http::StatusCode;
1522
    use axum::response::{IntoResponse, Response};
1523
    use axum_extra::extract::{Cached, WithRejection};
1524
    use reqwest::RequestBuilder;
1525

1526
    pub mod route {
1527
        pub const CACHED: &str = "/cached";
1528
        pub const CACHED_MODIFIED: &str = "/cached_modified";
1529
        pub const CACHED_VALIDIFIED_BY_REF: &str = "/cached_validified_by_ref";
1530
        pub const WITH_REJECTION: &str = "/with_rejection";
1531
        pub const WITH_REJECTION_MODIFIED: &str = "/with_rejection_modified";
1532
        pub const WITH_REJECTION_VALIDIFIED_BY_REF: &str = "/with_rejection_validified_by_ref";
1533
        pub const WITH_REJECTION_VALIDIFY: &str = "/with_rejection_validify";
1534
        pub const WITH_REJECTION_VALIDIFY_MODIFIED: &str = "/with_rejection_validify_modified";
1535
        pub const WITH_REJECTION_VALIDIFY_VALIDIFIED_BY_REF: &str =
1536
            "/with_rejection_validify_validified_by_ref";
1537
    }
1538

1539
    pub const PARAMETERS_HEADER: &str = "parameters-header";
1540
    pub const CACHED_REJECTION_STATUS: StatusCode = StatusCode::FORBIDDEN;
1541

1542
    //  1.2. Define you own `Rejection` type and implement `IntoResponse` for it.
1543
    pub enum ParametersRejection {
1544
        Null,
1545
        InvalidJson(serde_json::error::Error),
1546
    }
1547

1548
    impl IntoResponse for ParametersRejection {
1549
        fn into_response(self) -> Response {
3✔
1550
            match self {
3✔
1551
                ParametersRejection::Null => {
UNCOV
1552
                    (CACHED_REJECTION_STATUS, "My-Data header is missing").into_response()
×
1553
                }
1554
                ParametersRejection::InvalidJson(e) => (
6✔
1555
                    CACHED_REJECTION_STATUS,
1556
                    format!("My-Data is not valid json string: {e}"),
3✔
1557
                )
1558
                    .into_response(),
1559
            }
1560
        }
1561
    }
1562

1563
    //  1.3. Implement your extractor (`FromRequestParts` or `FromRequest`)
1564
    #[axum::async_trait]
1565
    impl<S> FromRequestParts<S> for ParametersValidify
1566
    where
1567
        S: Send + Sync,
1568
    {
1569
        type Rejection = ParametersRejection;
1570

1571
        async fn from_request_parts(parts: &mut Parts, _: &S) -> Result<Self, Self::Rejection> {
15✔
1572
            let Some(value) = parts.headers.get(PARAMETERS_HEADER) else {
3✔
UNCOV
1573
                return Err(ParametersRejection::Null);
×
1574
            };
1575

1576
            serde_json::from_slice(value.as_bytes()).map_err(ParametersRejection::InvalidJson)
6✔
1577
        }
1578
    }
1579

1580
    impl ValidTest for ParametersValidify {
1581
        const ERROR_STATUS_CODE: StatusCode = CACHED_REJECTION_STATUS;
1582

1583
        fn set_valid_request(builder: RequestBuilder) -> RequestBuilder {
3✔
1584
            builder.header(
6✔
1585
                PARAMETERS_HEADER,
1586
                serde_json::to_string(ParametersValidify::valid())
6✔
1587
                    .expect("Failed to serialize parameters"),
1588
            )
1589
        }
1590

1591
        fn set_error_request(builder: RequestBuilder) -> RequestBuilder {
3✔
1592
            builder.header(
6✔
1593
                PARAMETERS_HEADER,
1594
                serde_json::to_string(ParametersValidify::error())
6✔
1595
                    .expect("Failed to serialize parameters"),
1596
            )
1597
        }
1598

1599
        fn set_invalid_request(builder: RequestBuilder) -> RequestBuilder {
3✔
1600
            builder.header(
6✔
1601
                PARAMETERS_HEADER,
1602
                serde_json::to_string(ParametersValidify::invalid())
6✔
1603
                    .expect("Failed to serialize parameters"),
1604
            )
1605
        }
1606
    }
1607

1608
    impl HasModify for ParametersValidify {
1609
        type Modify = Self;
1610

1611
        fn get_modify(&mut self) -> &mut Self::Modify {
3✔
1612
            self
1613
        }
1614
    }
1615

1616
    pub struct ValidifyWithRejectionRejection {
1617
        inner: ParametersRejection,
1618
    }
1619

1620
    impl Rejection for ValidifyWithRejectionRejection {
1621
        const STATUS_CODE: StatusCode = StatusCode::CONFLICT;
1622
    }
1623

1624
    impl IntoResponse for ValidifyWithRejectionRejection {
1625
        fn into_response(self) -> Response {
3✔
1626
            let mut response = self.inner.into_response();
3✔
1627
            *response.status_mut() = Self::STATUS_CODE;
6✔
1628
            response
3✔
1629
        }
1630
    }
1631

1632
    // satisfy the `WithRejection`'s extractor trait bound
1633
    // R: From<E::Rejection> + IntoResponse
1634
    impl From<ParametersRejection> for ValidifyWithRejectionRejection {
1635
        fn from(inner: ParametersRejection) -> Self {
3✔
1636
            Self { inner }
1637
        }
1638
    }
1639

1640
    pub async fn extract_cached(
3✔
1641
        Validated(Cached(parameters)): Validated<Cached<ParametersValidify>>,
1642
    ) -> StatusCode {
1643
        check_validated(&parameters)
3✔
1644
    }
1645

1646
    pub async fn extract_cached_modified(
3✔
1647
        Modified(Cached(parameters)): Modified<Cached<ParametersValidify>>,
1648
    ) -> StatusCode {
1649
        check_modified(&parameters)
3✔
1650
    }
1651

1652
    pub async fn extract_cached_validified_by_ref(
3✔
1653
        ValidifiedByRef(Cached(parameters)): ValidifiedByRef<Cached<ParametersValidify>>,
1654
    ) -> StatusCode {
1655
        check_validified(&parameters)
3✔
1656
    }
1657

1658
    pub async fn extract_with_rejection(
3✔
1659
        Validated(WithRejection(parameters, _)): Validated<
1660
            WithRejection<ParametersValidify, ValidifyWithRejectionRejection>,
1661
        >,
1662
    ) -> StatusCode {
1663
        check_validated(&parameters)
3✔
1664
    }
1665

1666
    pub async fn extract_with_rejection_modified(
3✔
1667
        Modified(WithRejection(parameters, _)): Modified<
1668
            WithRejection<ParametersValidify, ValidifyWithRejectionRejection>,
1669
        >,
1670
    ) -> StatusCode {
1671
        check_modified(&parameters)
3✔
1672
    }
1673

1674
    pub async fn extract_with_rejection_validified_by_ref(
3✔
1675
        ValidifiedByRef(WithRejection(parameters, _)): ValidifiedByRef<
1676
            WithRejection<ParametersValidify, ValidifyWithRejectionRejection>,
1677
        >,
1678
    ) -> StatusCode {
1679
        check_validified(&parameters)
3✔
1680
    }
1681

1682
    pub struct WithRejectionValidifyRejection<E> {
1683
        inner: ValidifyRejection<E>,
1684
    }
1685

1686
    impl<E> From<ValidifyRejection<E>> for WithRejectionValidifyRejection<E> {
1687
        fn from(inner: ValidifyRejection<E>) -> Self {
3✔
1688
            Self { inner }
1689
        }
1690
    }
1691

1692
    impl<E: IntoResponse> IntoResponse for WithRejectionValidifyRejection<E> {
1693
        fn into_response(self) -> Response {
3✔
1694
            let mut res = self.inner.into_response();
3✔
1695
            *res.status_mut() = StatusCode::IM_A_TEAPOT;
6✔
1696
            res
3✔
1697
        }
1698
    }
1699

1700
    pub async fn extract_with_rejection_validifiy(
3✔
1701
        WithRejection(Validated(parameters), _): WithRejection<
1702
            Validated<ParametersValidify>,
1703
            WithRejectionValidifyRejection<ParametersRejection>,
1704
        >,
1705
    ) -> StatusCode {
1706
        check_validated(&parameters)
3✔
1707
    }
1708

1709
    pub async fn extract_with_rejection_validifiy_modified(
3✔
1710
        WithRejection(Modified(parameters), _): WithRejection<
1711
            Modified<ParametersValidify>,
1712
            ValidifyWithRejectionRejection,
1713
        >,
1714
    ) -> StatusCode {
1715
        check_modified(&parameters)
3✔
1716
    }
1717

1718
    pub async fn extract_with_rejection_validifiy_validified_by_ref(
3✔
1719
        WithRejection(ValidifiedByRef(parameters), _): WithRejection<
1720
            ValidifiedByRef<ParametersValidify>,
1721
            WithRejectionValidifyRejection<ParametersRejection>,
1722
        >,
1723
    ) -> StatusCode {
1724
        check_validified(&parameters)
3✔
1725
    }
1726
}
1727

1728
#[cfg(feature = "extra_typed_path")]
1729
mod extra_typed_path {
1730
    use super::{check_modified, check_validated, check_validified};
1731
    use crate::{HasModify, HasValidate, Modified, Validated, ValidifiedByRef};
1732
    use axum::http::StatusCode;
1733
    use axum_extra::routing::TypedPath;
1734
    use serde::Deserialize;
1735
    use validify::{Validate, Validify};
1736

1737
    pub mod route {
1738
        pub const EXTRA_TYPED_PATH: &str = "/extra_typed_path/:v0/:v1";
1739
        pub const EXTRA_TYPED_PATH_MODIFIED: &str = "/extra_typed_path_modified/:v0/:v1";
1740
        pub const EXTRA_TYPED_PATH_VALIDIFIED_BY_REF: &str =
1741
            "/extra_typed_path_validified_by_ref/:v0/:v1";
1742
    }
1743

1744
    #[derive(Validate, TypedPath, Deserialize)]
1745
    #[typed_path("/extra_typed_path/:v0/:v1")]
1746
    pub struct TypedPathParam {
1747
        #[validate(range(min = 5.0, max = 10.0))]
1748
        v0: i32,
1749
        #[validate(length(min = 1, max = 10))]
1750
        v1: String,
1751
    }
1752

1753
    impl HasValidate for TypedPathParam {
1754
        type Validate = Self;
1755

1756
        fn get_validate(&self) -> &Self::Validate {
3✔
1757
            self
1758
        }
1759
    }
1760

1761
    #[derive(Validify, TypedPath, Deserialize, Clone, PartialEq, Eq)]
1762
    #[typed_path("/extra_typed_path_validified_by_ref/:v0/:v1")]
1763
    pub struct TypedPathParamValidifiedByRef {
1764
        #[validate(range(min = 5.0, max = 10.0))]
1765
        v0: i32,
1766
        #[modify(lowercase)]
1767
        #[validate(length(min = 1, max = 10))]
1768
        v1: String,
1769
    }
1770

1771
    impl HasValidate for TypedPathParamValidifiedByRef {
1772
        type Validate = Self;
1773

1774
        fn get_validate(&self) -> &Self::Validate {
3✔
1775
            self
1776
        }
1777
    }
1778

1779
    impl HasModify for TypedPathParamValidifiedByRef {
1780
        type Modify = Self;
1781

1782
        fn get_modify(&mut self) -> &mut Self::Modify {
3✔
1783
            self
1784
        }
1785
    }
1786

1787
    #[derive(Validify, TypedPath, Deserialize, Clone, PartialEq, Eq)]
1788
    #[typed_path("/extra_typed_path_modified/:v0/:v1")]
1789
    pub struct TypedPathParamModified {
1790
        #[validate(range(min = 5.0, max = 10.0))]
1791
        v0: i32,
1792
        #[modify(lowercase)]
1793
        #[validate(length(min = 1, max = 10))]
1794
        v1: String,
1795
    }
1796

1797
    impl HasModify for TypedPathParamModified {
1798
        type Modify = Self;
1799

1800
        fn get_modify(&mut self) -> &mut Self::Modify {
3✔
1801
            self
1802
        }
1803
    }
1804

1805
    pub async fn extract_extra_typed_path(
3✔
1806
        Validated(param): Validated<TypedPathParam>,
1807
    ) -> StatusCode {
1808
        check_validated(&param)
3✔
1809
    }
1810

1811
    pub async fn extract_extra_typed_path_modified(
3✔
1812
        Modified(param): Modified<TypedPathParamModified>,
1813
    ) -> StatusCode {
1814
        check_modified(&param)
3✔
1815
    }
1816

1817
    pub async fn extract_extra_typed_path_validified_by_ref(
3✔
1818
        ValidifiedByRef(param): ValidifiedByRef<TypedPathParamValidifiedByRef>,
1819
    ) -> StatusCode {
1820
        check_validified(&param)
3✔
1821
    }
1822
}
1823

1824
#[cfg(feature = "extra_query")]
1825
mod extra_query {
1826
    use super::{check_modified, check_validated, check_validified, ParametersValidify};
1827
    use crate::{Modified, Validated, Validified, ValidifiedByRef};
1828
    use axum::http::StatusCode;
1829
    use axum_extra::extract::Query;
1830

1831
    pub mod route {
1832
        pub const EXTRA_QUERY: &str = "/extra_query";
1833
        pub const EXTRA_QUERY_MODIFIED: &str = "/extra_query_modified";
1834
        pub const EXTRA_QUERY_VALIDIFIED: &str = "/extra_query_validified";
1835
        pub const EXTRA_QUERY_VALIDIFIED_BY_REF: &str = "/extra_query_validified_by_ref";
1836
    }
1837

1838
    pub async fn extract_extra_query(
3✔
1839
        Validated(Query(parameters)): Validated<Query<ParametersValidify>>,
1840
    ) -> StatusCode {
1841
        check_validated(&parameters)
3✔
1842
    }
1843

1844
    pub async fn extract_extra_query_modified(
3✔
1845
        Modified(Query(parameters)): Modified<Query<ParametersValidify>>,
1846
    ) -> StatusCode {
1847
        check_modified(&parameters)
3✔
1848
    }
1849

1850
    pub async fn extract_extra_query_validified(
3✔
1851
        Validified(Query(parameters)): Validified<Query<ParametersValidify>>,
1852
    ) -> StatusCode {
1853
        check_validified(&parameters)
3✔
1854
    }
1855

1856
    pub async fn extract_extra_query_validified_by_ref(
3✔
1857
        ValidifiedByRef(Query(parameters)): ValidifiedByRef<Query<ParametersValidify>>,
1858
    ) -> StatusCode {
1859
        check_validified(&parameters)
3✔
1860
    }
1861
}
1862

1863
#[cfg(feature = "extra_form")]
1864
mod extra_form {
1865
    use super::{check_modified, check_validated, check_validified, ParametersValidify};
1866
    use crate::{Modified, Validated, Validified, ValidifiedByRef};
1867
    use axum::http::StatusCode;
1868
    use axum_extra::extract::Form;
1869

1870
    pub mod route {
1871
        pub const EXTRA_FORM: &str = "/extra_form";
1872
        pub const EXTRA_FORM_MODIFIED: &str = "/extra_form_modified";
1873
        pub const EXTRA_FORM_VALIDIFED: &str = "/extra_form_validifed";
1874
        pub const EXTRA_FORM_VALIDIFED_BY_REF: &str = "/extra_form_validified_by_ref";
1875
    }
1876

1877
    pub async fn extract_extra_form(
3✔
1878
        Validated(Form(parameters)): Validated<Form<ParametersValidify>>,
1879
    ) -> StatusCode {
1880
        check_validated(&parameters)
3✔
1881
    }
1882

1883
    pub async fn extract_extra_form_modified(
3✔
1884
        Modified(Form(parameters)): Modified<Form<ParametersValidify>>,
1885
    ) -> StatusCode {
1886
        check_modified(&parameters)
3✔
1887
    }
1888

1889
    pub async fn extract_extra_form_validifed(
3✔
1890
        Validified(Form(parameters)): Validified<Form<ParametersValidify>>,
1891
    ) -> StatusCode {
1892
        check_validified(&parameters)
3✔
1893
    }
1894

1895
    pub async fn extract_extra_form_validifed_by_ref(
3✔
1896
        ValidifiedByRef(Form(parameters)): ValidifiedByRef<Form<ParametersValidify>>,
1897
    ) -> StatusCode {
1898
        check_validified(&parameters)
3✔
1899
    }
1900
}
1901

1902
#[cfg(feature = "extra_protobuf")]
1903
mod extra_protobuf {
1904
    use super::{
1905
        check_modified, check_validated, check_validified, ParametersValidifyWithoutPayload,
1906
    };
1907
    use crate::{Modified, Validated, ValidifiedByRef};
1908
    use axum::http::StatusCode;
1909
    use axum_extra::protobuf::Protobuf;
1910

1911
    pub mod route {
1912
        pub const EXTRA_PROTOBUF: &str = "/extra_protobuf";
1913
        pub const EXTRA_PROTOBUF_MODIFIED: &str = "/extra_protobuf_modified";
1914
        pub const EXTRA_PROTOBUF_VALIDIFIED_BY_REF: &str = "/extra_protobuf_validified_by_ref";
1915
    }
1916

1917
    pub async fn extract_extra_protobuf(
3✔
1918
        Validated(Protobuf(parameters)): Validated<Protobuf<ParametersValidifyWithoutPayload>>,
1919
    ) -> StatusCode {
1920
        check_validated(&parameters)
3✔
1921
    }
1922

1923
    pub async fn extract_extra_protobuf_modified(
3✔
1924
        Modified(Protobuf(parameters)): Modified<Protobuf<ParametersValidifyWithoutPayload>>,
1925
    ) -> StatusCode {
1926
        check_modified(&parameters)
3✔
1927
    }
1928

1929
    pub async fn extract_extra_protobuf_validified_by_ref(
3✔
1930
        ValidifiedByRef(Protobuf(parameters)): ValidifiedByRef<
1931
            Protobuf<ParametersValidifyWithoutPayload>,
1932
        >,
1933
    ) -> StatusCode {
1934
        check_validified(&parameters)
3✔
1935
    }
1936
}
1937

1938
#[cfg(feature = "yaml")]
1939
mod yaml {
1940
    use super::{check_modified, check_validated, check_validified, ParametersValidify};
1941
    use crate::{Modified, Validated, Validified, ValidifiedByRef};
1942
    use axum::http::StatusCode;
1943
    use axum_serde::Yaml;
1944

1945
    pub mod route {
1946
        pub const YAML: &str = "/yaml";
1947
        pub const YAML_MODIFIED: &str = "/yaml_modified";
1948
        pub const YAML_VALIDIFIED: &str = "/yaml_validified";
1949
        pub const YAML_VALIDIFIED_BY_REF: &str = "/yaml_validified_by_ref";
1950
    }
1951

1952
    pub async fn extract_yaml(
3✔
1953
        Validated(Yaml(parameters)): Validated<Yaml<ParametersValidify>>,
1954
    ) -> StatusCode {
1955
        check_validated(&parameters)
3✔
1956
    }
1957

1958
    pub async fn extract_yaml_modified(
3✔
1959
        Modified(Yaml(parameters)): Modified<Yaml<ParametersValidify>>,
1960
    ) -> StatusCode {
1961
        check_modified(&parameters)
3✔
1962
    }
1963

1964
    pub async fn extract_yaml_validified(
3✔
1965
        Validified(Yaml(parameters)): Validified<Yaml<ParametersValidify>>,
1966
    ) -> StatusCode {
1967
        check_validified(&parameters)
3✔
1968
    }
1969

1970
    pub async fn extract_yaml_validified_by_ref(
3✔
1971
        ValidifiedByRef(Yaml(parameters)): ValidifiedByRef<Yaml<ParametersValidify>>,
1972
    ) -> StatusCode {
1973
        check_validified(&parameters)
3✔
1974
    }
1975
}
1976

1977
#[cfg(feature = "msgpack")]
1978
mod msgpack {
1979
    use super::{check_modified, check_validated, check_validified, ParametersValidify};
1980
    use crate::{Modified, Validated, Validified, ValidifiedByRef};
1981
    use axum::http::StatusCode;
1982
    use axum_serde::{MsgPack, MsgPackRaw};
1983

1984
    pub mod route {
1985
        pub const MSGPACK: &str = "/msgpack";
1986
        pub const MSGPACK_MODIFIED: &str = "/msgpack_modified";
1987
        pub const MSGPACK_VALIDIFIED: &str = "/msgpack_validified";
1988
        pub const MSGPACK_VALIDIFIED_BY_REF: &str = "/msgpack_validified_by_ref";
1989
        pub const MSGPACK_RAW: &str = "/msgpack_raw";
1990
        pub const MSGPACK_RAW_MODIFIED: &str = "/msgpack_raw_modified";
1991
        pub const MSGPACK_RAW_VALIDIFIED: &str = "/msgpack_raw_validified";
1992
        pub const MSGPACK_RAW_VALIDIFIED_BY_REF: &str = "/msgpack_raw_validified_by_ref";
1993
    }
1994

1995
    pub async fn extract_msgpack(
3✔
1996
        Validated(MsgPack(parameters)): Validated<MsgPack<ParametersValidify>>,
1997
    ) -> StatusCode {
1998
        check_validated(&parameters)
3✔
1999
    }
2000

2001
    pub async fn extract_msgpack_modified(
3✔
2002
        Modified(MsgPack(parameters)): Modified<MsgPack<ParametersValidify>>,
2003
    ) -> StatusCode {
2004
        check_modified(&parameters)
3✔
2005
    }
2006

2007
    pub async fn extract_msgpack_validified(
3✔
2008
        Validified(MsgPack(parameters)): Validified<MsgPack<ParametersValidify>>,
2009
    ) -> StatusCode {
2010
        check_validified(&parameters)
3✔
2011
    }
2012

2013
    pub async fn extract_msgpack_validified_by_ref(
3✔
2014
        ValidifiedByRef(MsgPack(parameters)): ValidifiedByRef<MsgPack<ParametersValidify>>,
2015
    ) -> StatusCode {
2016
        check_validified(&parameters)
3✔
2017
    }
2018

2019
    pub async fn extract_msgpack_raw(
3✔
2020
        Validated(MsgPackRaw(parameters)): Validated<MsgPackRaw<ParametersValidify>>,
2021
    ) -> StatusCode {
2022
        check_validated(&parameters)
3✔
2023
    }
2024

2025
    pub async fn extract_msgpack_raw_modified(
3✔
2026
        Modified(MsgPackRaw(parameters)): Modified<MsgPackRaw<ParametersValidify>>,
2027
    ) -> StatusCode {
2028
        check_modified(&parameters)
3✔
2029
    }
2030

2031
    pub async fn extract_msgpack_raw_validified(
3✔
2032
        Validified(MsgPackRaw(parameters)): Validified<MsgPackRaw<ParametersValidify>>,
2033
    ) -> StatusCode {
2034
        check_validified(&parameters)
3✔
2035
    }
2036

2037
    pub async fn extract_msgpack_raw_validified_by_ref(
3✔
2038
        ValidifiedByRef(MsgPackRaw(parameters)): ValidifiedByRef<MsgPackRaw<ParametersValidify>>,
2039
    ) -> StatusCode {
2040
        check_validified(&parameters)
3✔
2041
    }
2042
}
2043

2044
#[cfg(feature = "xml")]
2045
mod xml {
2046
    use super::{check_modified, check_validated, check_validified, ParametersValidify};
2047
    use crate::{Modified, Validated, Validified, ValidifiedByRef};
2048
    use axum::http::StatusCode;
2049
    use axum_serde::Xml;
2050

2051
    pub mod route {
2052
        pub const XML: &str = "/xml";
2053
        pub const XML_MODIFIED: &str = "/xml_modified";
2054
        pub const XML_VALIDIFIED: &str = "/xml_validified";
2055
        pub const XML_VALIDIFIED_BY_REF: &str = "/xml_validified_by_ref";
2056
    }
2057

2058
    pub async fn extract_xml(
3✔
2059
        Validated(Xml(parameters)): Validated<Xml<ParametersValidify>>,
2060
    ) -> StatusCode {
2061
        check_validated(&parameters)
3✔
2062
    }
2063

2064
    pub async fn extract_xml_modified(
3✔
2065
        Modified(Xml(parameters)): Modified<Xml<ParametersValidify>>,
2066
    ) -> StatusCode {
2067
        check_modified(&parameters)
3✔
2068
    }
2069

2070
    pub async fn extract_xml_validified(
3✔
2071
        Validified(Xml(parameters)): Validified<Xml<ParametersValidify>>,
2072
    ) -> StatusCode {
2073
        check_validified(&parameters)
3✔
2074
    }
2075

2076
    pub async fn extract_xml_validified_by_ref(
3✔
2077
        ValidifiedByRef(Xml(parameters)): ValidifiedByRef<Xml<ParametersValidify>>,
2078
    ) -> StatusCode {
2079
        check_validified(&parameters)
3✔
2080
    }
2081
}
2082

2083
#[cfg(feature = "toml")]
2084
mod toml {
2085
    use super::{check_modified, check_validated, check_validified, ParametersValidify};
2086
    use crate::{Modified, Validated, Validified, ValidifiedByRef};
2087
    use axum::http::StatusCode;
2088
    use axum_serde::Toml;
2089

2090
    pub mod route {
2091
        pub const TOML: &str = "/toml";
2092
        pub const TOML_MODIFIED: &str = "/toml_modified";
2093
        pub const TOML_VALIDIFIED: &str = "/toml_validified";
2094
        pub const TOML_VALIDIFIED_BY_REF: &str = "/toml_validified_by_ref";
2095
    }
2096

2097
    pub async fn extract_toml(
3✔
2098
        Validated(Toml(parameters)): Validated<Toml<ParametersValidify>>,
2099
    ) -> StatusCode {
2100
        check_validated(&parameters)
3✔
2101
    }
2102

2103
    pub async fn extract_toml_modified(
3✔
2104
        Modified(Toml(parameters)): Modified<Toml<ParametersValidify>>,
2105
    ) -> StatusCode {
2106
        check_modified(&parameters)
3✔
2107
    }
2108

2109
    pub async fn extract_toml_validified(
3✔
2110
        Validified(Toml(parameters)): Validified<Toml<ParametersValidify>>,
2111
    ) -> StatusCode {
2112
        check_validified(&parameters)
3✔
2113
    }
2114

2115
    pub async fn extract_toml_validified_by_ref(
3✔
2116
        ValidifiedByRef(Toml(parameters)): ValidifiedByRef<Toml<ParametersValidify>>,
2117
    ) -> StatusCode {
2118
        check_validified(&parameters)
3✔
2119
    }
2120
}
2121

2122
#[cfg(feature = "sonic")]
2123
mod sonic {
2124
    use super::{check_modified, check_validated, check_validified, ParametersValidify};
2125
    use crate::{Modified, Validated, Validified, ValidifiedByRef};
2126
    use axum::http::StatusCode;
2127
    use axum_serde::Sonic;
2128

2129
    pub mod route {
2130
        pub const SONIC: &str = "/sonic";
2131
        pub const SONIC_MODIFIED: &str = "/sonic_modified";
2132
        pub const SONIC_VALIDIFIED: &str = "/sonic_validified";
2133
        pub const SONIC_VALIDIFIED_BY_REF: &str = "/sonic_validified_by_ref";
2134
    }
2135

2136
    pub async fn extract_sonic(
3✔
2137
        Validated(Sonic(parameters)): Validated<Sonic<ParametersValidify>>,
2138
    ) -> StatusCode {
2139
        check_validated(&parameters)
3✔
2140
    }
2141

2142
    pub async fn extract_sonic_modified(
3✔
2143
        Modified(Sonic(parameters)): Modified<Sonic<ParametersValidify>>,
2144
    ) -> StatusCode {
2145
        check_modified(&parameters)
3✔
2146
    }
2147

2148
    pub async fn extract_sonic_validified(
3✔
2149
        Validified(Sonic(parameters)): Validified<Sonic<ParametersValidify>>,
2150
    ) -> StatusCode {
2151
        check_validified(&parameters)
3✔
2152
    }
2153

2154
    pub async fn extract_sonic_validified_by_ref(
3✔
2155
        ValidifiedByRef(Sonic(parameters)): ValidifiedByRef<Sonic<ParametersValidify>>,
2156
    ) -> StatusCode {
2157
        check_validified(&parameters)
3✔
2158
    }
2159
}
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