xitca_web/handler/types/
params.rs

1//! type extractor for uri params.
2
3use core::{marker::PhantomData, ops::Deref};
4
5use serde::{
6    Deserialize,
7    de::{self, Deserializer, Error as DeError, Visitor},
8    forward_to_deserialize_any,
9};
10
11use xitca_http::util::service::router;
12
13use crate::{context::WebContext, error::Error, handler::FromRequest};
14
15#[derive(Debug)]
16pub struct Params<T>(pub T);
17
18impl<'a, 'r, T, C, B> FromRequest<'a, WebContext<'r, C, B>> for Params<T>
19where
20    T: for<'de> Deserialize<'de>,
21{
22    type Type<'b> = Params<T>;
23    type Error = Error;
24
25    #[inline]
26    async fn from_request(ctx: &'a WebContext<'r, C, B>) -> Result<Self, Self::Error> {
27        let params = ctx.req().body().params();
28        T::deserialize(Params2::new(params)).map(Params).map_err(Into::into)
29    }
30}
31
32/// lazy deserialize type.
33/// it lowers the deserialization to handler function where zero copy deserialize can happen.
34pub struct LazyParams<'a, T> {
35    params: Params2<'a>,
36    _params: PhantomData<T>,
37}
38
39impl<T> LazyParams<'_, T> {
40    pub fn deserialize<'de>(&'de self) -> Result<T, Error>
41    where
42        T: Deserialize<'de>,
43    {
44        T::deserialize(self.params).map_err(Into::into)
45    }
46}
47
48impl<'a, 'r, C, B, T> FromRequest<'a, WebContext<'r, C, B>> for LazyParams<'a, T> {
49    type Type<'b> = LazyParams<'b, T>;
50    type Error = Error;
51
52    #[inline]
53    async fn from_request(ctx: &'a WebContext<'r, C, B>) -> Result<Self, Self::Error> {
54        Ok(LazyParams {
55            params: Params2::new(ctx.req().body().params()),
56            _params: PhantomData,
57        })
58    }
59}
60
61#[derive(Debug)]
62pub struct ParamsRef<'a>(&'a router::Params);
63
64impl Deref for ParamsRef<'_> {
65    type Target = router::Params;
66
67    fn deref(&self) -> &Self::Target {
68        self.0
69    }
70}
71
72impl<'a, 'r, C, B> FromRequest<'a, WebContext<'r, C, B>> for ParamsRef<'a> {
73    type Type<'b> = ParamsRef<'b>;
74    type Error = Error;
75
76    #[inline]
77    async fn from_request(ctx: &'a WebContext<'r, C, B>) -> Result<Self, Self::Error> {
78        Ok(ParamsRef(ctx.req().body().params()))
79    }
80}
81
82macro_rules! unsupported_type {
83    ($trait_fn:ident, $name:expr) => {
84        fn $trait_fn<V>(self, _: V) -> Result<V::Value, Self::Error>
85        where
86            V: Visitor<'de>,
87        {
88            Err(de::value::Error::custom(concat!("unsupported type: ", $name)))
89        }
90    };
91}
92
93macro_rules! parse_single_value {
94    ($trait_fn:ident, $visit_fn:ident, $tp:tt) => {
95        fn $trait_fn<V>(self, visitor: V) -> Result<V::Value, Self::Error>
96        where
97            V: Visitor<'de>,
98        {
99            if self.params.len() != 1 {
100                return Err(de::value::Error::custom(format!(
101                    "wrong number of parameters: {} expected 1",
102                    self.params.len()
103                )));
104            }
105
106            let param = self.params.iter().next().unwrap().1;
107            let v = param
108                .parse()
109                .map_err(|_| de::value::Error::custom(format!("can not parse {param:?} to a {}", $tp)))?;
110            visitor.$visit_fn(v)
111        }
112    };
113}
114
115#[derive(Clone, Copy)]
116pub struct Params2<'de> {
117    params: &'de router::Params,
118}
119
120impl<'a> Params2<'a> {
121    #[inline]
122    pub fn new(params: &'a router::Params) -> Self {
123        Params2 { params }
124    }
125}
126
127impl<'de> Deserializer<'de> for Params2<'de> {
128    type Error = de::value::Error;
129
130    fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
131    where
132        V: Visitor<'de>,
133    {
134        match self.params.iter().next() {
135            Some((_, v)) => visitor.visit_borrowed_str(v),
136            None => Err(de::value::Error::custom("expected at least one parameters")),
137        }
138    }
139
140    fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
141    where
142        V: Visitor<'de>,
143    {
144        visitor.visit_unit()
145    }
146
147    fn deserialize_unit_struct<V>(self, _: &'static str, visitor: V) -> Result<V::Value, Self::Error>
148    where
149        V: Visitor<'de>,
150    {
151        self.deserialize_unit(visitor)
152    }
153
154    fn deserialize_newtype_struct<V>(self, _: &'static str, visitor: V) -> Result<V::Value, Self::Error>
155    where
156        V: Visitor<'de>,
157    {
158        visitor.visit_newtype_struct(self)
159    }
160
161    fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
162    where
163        V: Visitor<'de>,
164    {
165        visitor.visit_seq(SeqAccess {
166            params: self.params.iter(),
167        })
168    }
169
170    fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value, Self::Error>
171    where
172        V: Visitor<'de>,
173    {
174        if self.params.len() < len {
175            Err(de::value::Error::custom(
176                format!("wrong number of parameters: {} expected {}", self.params.len(), len).as_str(),
177            ))
178        } else {
179            visitor.visit_seq(SeqAccess {
180                params: self.params.iter(),
181            })
182        }
183    }
184
185    fn deserialize_tuple_struct<V>(self, _: &'static str, len: usize, visitor: V) -> Result<V::Value, Self::Error>
186    where
187        V: Visitor<'de>,
188    {
189        if self.params.len() < len {
190            Err(de::value::Error::custom(
191                format!("wrong number of parameters: {} expected {}", self.params.len(), len).as_str(),
192            ))
193        } else {
194            visitor.visit_seq(SeqAccess {
195                params: self.params.iter(),
196            })
197        }
198    }
199
200    fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
201    where
202        V: Visitor<'de>,
203    {
204        visitor.visit_map(MapAccess {
205            params: self.params.iter(),
206            current: None,
207        })
208    }
209
210    fn deserialize_struct<V>(
211        self,
212        _: &'static str,
213        _: &'static [&'static str],
214        visitor: V,
215    ) -> Result<V::Value, Self::Error>
216    where
217        V: Visitor<'de>,
218    {
219        self.deserialize_map(visitor)
220    }
221
222    fn deserialize_enum<V>(
223        self,
224        _: &'static str,
225        _: &'static [&'static str],
226        visitor: V,
227    ) -> Result<V::Value, Self::Error>
228    where
229        V: Visitor<'de>,
230    {
231        match self.params.iter().next() {
232            Some((_, value)) => visitor.visit_enum(ValueEnum { value }),
233            None => Err(de::value::Error::custom("expected at least one parameters")),
234        }
235    }
236
237    unsupported_type!(deserialize_any, "'any'");
238    unsupported_type!(deserialize_bytes, "bytes");
239    unsupported_type!(deserialize_option, "Option<T>");
240    unsupported_type!(deserialize_identifier, "identifier");
241    unsupported_type!(deserialize_ignored_any, "ignored_any");
242
243    parse_single_value!(deserialize_bool, visit_bool, "bool");
244    parse_single_value!(deserialize_i8, visit_i8, "i8");
245    parse_single_value!(deserialize_i16, visit_i16, "i16");
246    parse_single_value!(deserialize_i32, visit_i32, "i32");
247    parse_single_value!(deserialize_i64, visit_i64, "i64");
248    parse_single_value!(deserialize_u8, visit_u8, "u8");
249    parse_single_value!(deserialize_u16, visit_u16, "u16");
250    parse_single_value!(deserialize_u32, visit_u32, "u32");
251    parse_single_value!(deserialize_u64, visit_u64, "u64");
252    parse_single_value!(deserialize_f32, visit_f32, "f32");
253    parse_single_value!(deserialize_f64, visit_f64, "f64");
254    parse_single_value!(deserialize_string, visit_string, "String");
255    parse_single_value!(deserialize_byte_buf, visit_string, "String");
256    parse_single_value!(deserialize_char, visit_char, "char");
257}
258
259struct MapAccess<'de, I> {
260    params: I,
261    current: Option<(&'de str, &'de str)>,
262}
263
264impl<'de, I> de::MapAccess<'de> for MapAccess<'de, I>
265where
266    I: Iterator<Item = (&'de str, &'de str)>,
267{
268    type Error = de::value::Error;
269
270    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
271    where
272        K: de::DeserializeSeed<'de>,
273    {
274        self.current = self.params.next();
275        match self.current {
276            Some((key, _)) => Ok(Some(seed.deserialize(Key { key })?)),
277            None => Ok(None),
278        }
279    }
280
281    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>
282    where
283        V: de::DeserializeSeed<'de>,
284    {
285        if let Some((_, value)) = self.current.take() {
286            seed.deserialize(Value { value })
287        } else {
288            Err(de::value::Error::custom("unexpected item"))
289        }
290    }
291}
292
293struct Key<'de> {
294    key: &'de str,
295}
296
297impl<'de> Deserializer<'de> for Key<'de> {
298    type Error = de::value::Error;
299
300    fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
301    where
302        V: Visitor<'de>,
303    {
304        Err(de::value::Error::custom("Unexpected"))
305    }
306
307    fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value, Self::Error>
308    where
309        V: Visitor<'de>,
310    {
311        visitor.visit_str(self.key)
312    }
313
314    forward_to_deserialize_any! {
315        bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
316            byte_buf option unit unit_struct newtype_struct seq tuple
317            tuple_struct map struct enum ignored_any
318    }
319}
320
321macro_rules! parse_value {
322    ($trait_fn:ident, $visit_fn:ident, $tp:tt) => {
323        fn $trait_fn<V>(self, visitor: V) -> Result<V::Value, Self::Error>
324        where
325            V: Visitor<'de>,
326        {
327            let v = self
328                .value
329                .parse()
330                .map_err(|_| de::value::Error::custom(format!("can not parse {:?} to a {}", self.value, $tp)))?;
331            visitor.$visit_fn(v)
332        }
333    };
334}
335
336struct Value<'de> {
337    value: &'de str,
338}
339
340impl<'de> Deserializer<'de> for Value<'de> {
341    type Error = de::value::Error;
342
343    parse_value!(deserialize_bool, visit_bool, "bool");
344    parse_value!(deserialize_i8, visit_i8, "i8");
345    parse_value!(deserialize_i16, visit_i16, "i16");
346    parse_value!(deserialize_i32, visit_i32, "i16");
347    parse_value!(deserialize_i64, visit_i64, "i64");
348    parse_value!(deserialize_u8, visit_u8, "u8");
349    parse_value!(deserialize_u16, visit_u16, "u16");
350    parse_value!(deserialize_u32, visit_u32, "u32");
351    parse_value!(deserialize_u64, visit_u64, "u64");
352    parse_value!(deserialize_f32, visit_f32, "f32");
353    parse_value!(deserialize_f64, visit_f64, "f64");
354    parse_value!(deserialize_string, visit_string, "String");
355    parse_value!(deserialize_byte_buf, visit_string, "String");
356    parse_value!(deserialize_char, visit_char, "char");
357
358    fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
359    where
360        V: Visitor<'de>,
361    {
362        visitor.visit_borrowed_str(self.value)
363    }
364
365    fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value, Self::Error>
366    where
367        V: Visitor<'de>,
368    {
369        visitor.visit_borrowed_bytes(self.value.as_bytes())
370    }
371
372    fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
373    where
374        V: Visitor<'de>,
375    {
376        visitor.visit_some(self)
377    }
378
379    fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
380    where
381        V: Visitor<'de>,
382    {
383        visitor.visit_unit()
384    }
385
386    fn deserialize_unit_struct<V>(self, _: &'static str, visitor: V) -> Result<V::Value, Self::Error>
387    where
388        V: Visitor<'de>,
389    {
390        visitor.visit_unit()
391    }
392
393    fn deserialize_newtype_struct<V>(self, _: &'static str, visitor: V) -> Result<V::Value, Self::Error>
394    where
395        V: Visitor<'de>,
396    {
397        visitor.visit_newtype_struct(self)
398    }
399
400    fn deserialize_tuple<V>(self, _: usize, _: V) -> Result<V::Value, Self::Error>
401    where
402        V: Visitor<'de>,
403    {
404        Err(de::value::Error::custom("unsupported type: tuple"))
405    }
406
407    fn deserialize_tuple_struct<V>(self, _: &'static str, _: usize, _: V) -> Result<V::Value, Self::Error>
408    where
409        V: Visitor<'de>,
410    {
411        Err(de::value::Error::custom("unsupported type: tuple struct"))
412    }
413
414    fn deserialize_struct<V>(self, _: &'static str, _: &'static [&'static str], _: V) -> Result<V::Value, Self::Error>
415    where
416        V: Visitor<'de>,
417    {
418        Err(de::value::Error::custom("unsupported type: struct"))
419    }
420
421    fn deserialize_enum<V>(
422        self,
423        _: &'static str,
424        _: &'static [&'static str],
425        visitor: V,
426    ) -> Result<V::Value, Self::Error>
427    where
428        V: Visitor<'de>,
429    {
430        visitor.visit_enum(ValueEnum { value: self.value })
431    }
432
433    fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
434    where
435        V: Visitor<'de>,
436    {
437        visitor.visit_unit()
438    }
439
440    unsupported_type!(deserialize_any, "any");
441    unsupported_type!(deserialize_seq, "seq");
442    unsupported_type!(deserialize_map, "map");
443    unsupported_type!(deserialize_identifier, "identifier");
444}
445
446struct SeqAccess<I> {
447    params: I,
448}
449
450impl<'de, I> de::SeqAccess<'de> for SeqAccess<I>
451where
452    I: Iterator<Item = (&'de str, &'de str)>,
453{
454    type Error = de::value::Error;
455
456    fn next_element_seed<U>(&mut self, seed: U) -> Result<Option<U::Value>, Self::Error>
457    where
458        U: de::DeserializeSeed<'de>,
459    {
460        match self.params.next() {
461            Some((_, value)) => Ok(Some(seed.deserialize(Value { value })?)),
462            None => Ok(None),
463        }
464    }
465}
466
467struct ValueEnum<'de> {
468    value: &'de str,
469}
470
471impl<'de> de::EnumAccess<'de> for ValueEnum<'de> {
472    type Error = de::value::Error;
473    type Variant = UnitVariant;
474
475    fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error>
476    where
477        V: de::DeserializeSeed<'de>,
478    {
479        Ok((seed.deserialize(Key { key: self.value })?, UnitVariant))
480    }
481}
482
483struct UnitVariant;
484
485impl<'de> de::VariantAccess<'de> for UnitVariant {
486    type Error = de::value::Error;
487
488    fn unit_variant(self) -> Result<(), Self::Error> {
489        Ok(())
490    }
491
492    fn newtype_variant_seed<T>(self, _seed: T) -> Result<T::Value, Self::Error>
493    where
494        T: de::DeserializeSeed<'de>,
495    {
496        Err(de::value::Error::custom("not supported"))
497    }
498
499    fn tuple_variant<V>(self, _len: usize, _visitor: V) -> Result<V::Value, Self::Error>
500    where
501        V: Visitor<'de>,
502    {
503        Err(de::value::Error::custom("not supported"))
504    }
505
506    fn struct_variant<V>(self, _: &'static [&'static str], _: V) -> Result<V::Value, Self::Error>
507    where
508        V: Visitor<'de>,
509    {
510        Err(de::value::Error::custom("not supported"))
511    }
512}
513
514#[cfg(test)]
515mod tests {
516    use core::convert::Infallible;
517
518    use serde::Deserialize;
519    use xitca_http::util::service::{handler::handler_service, router::Router};
520    use xitca_unsafe_collection::futures::NowOrPanic;
521
522    use crate::{
523        App,
524        http::{Request, RequestExt, Uri},
525        service::{Service, fn_service},
526        test::collect_string_body,
527    };
528
529    use super::*;
530
531    #[derive(Deserialize)]
532    struct MyStruct {
533        key: String,
534        value: String,
535    }
536
537    #[derive(Debug, Deserialize)]
538    struct Test1(String, u32);
539
540    #[derive(Debug, Deserialize)]
541    struct Test2 {
542        key: String,
543        value: u32,
544    }
545
546    #[derive(Debug, Deserialize, PartialEq)]
547    #[serde(rename_all = "lowercase")]
548    enum TestEnum {
549        Val1,
550        Val2,
551    }
552
553    async fn handler(req: Request<RequestExt<()>>) -> Result<Request<RequestExt<()>>, Infallible> {
554        Ok(req)
555    }
556
557    #[test]
558    fn test_request_extract() {
559        let service = Router::new()
560            .insert("/:key/:value/", fn_service(handler))
561            .call(())
562            .now_or_panic()
563            .unwrap();
564
565        let mut req = crate::http::WebRequest::default();
566        *req.uri_mut() = Uri::from_static("/name/user1/");
567
568        let res = service.call(req).now_or_panic().unwrap();
569
570        let params = res.body().params();
571
572        let _: () = Deserialize::deserialize(Params2::new(params)).unwrap();
573
574        let MyStruct { key, value } = Deserialize::deserialize(Params2::new(params)).unwrap();
575        assert_eq!(key, "name");
576        assert_eq!(value, "user1");
577
578        let (key, value): (String, &str) = Deserialize::deserialize(Params2::new(params)).unwrap();
579        assert_eq!(key, "name");
580        assert_eq!(value, "user1");
581
582        let s: &str = de::Deserialize::deserialize(Params2::new(params)).unwrap();
583        assert_eq!(s, "name");
584
585        let mut req = crate::http::WebRequest::default();
586        *req.uri_mut() = Uri::from_static("/name/32/");
587
588        let res = service.call(req).now_or_panic().unwrap();
589        let params = res.body().params();
590
591        let Test1(key, value) = Deserialize::deserialize(Params2::new(params)).unwrap();
592        assert_eq!(key, "name");
593        assert_eq!(value, 32);
594
595        let Test2 { key, value } = Deserialize::deserialize(Params2::new(params)).unwrap();
596        assert_eq!(key, "name");
597        assert_eq!(value, 32);
598
599        #[derive(Deserialize)]
600        struct T(Test1);
601        let T(Test1(key, value)) = Deserialize::deserialize(Params2::new(params)).unwrap();
602        assert_eq!(key, "name");
603        assert_eq!(value, 32);
604
605        let s: Result<(Test2,), _> = Deserialize::deserialize(Params2::new(params));
606        assert!(s.is_err());
607
608        let (key, value): (String, u8) = Deserialize::deserialize(Params2::new(params)).unwrap();
609        assert_eq!(key, "name");
610        assert_eq!(value, 32);
611
612        let res: Vec<String> = Deserialize::deserialize(Params2::new(params)).unwrap();
613        assert_eq!(res[0], "name");
614        assert_eq!(res[1], "32");
615
616        #[derive(Debug, Deserialize)]
617        struct S2(());
618        let s: Result<S2, de::value::Error> = Deserialize::deserialize(Params2::new(params));
619        assert!(s.is_ok());
620
621        let s: Result<(), de::value::Error> = Deserialize::deserialize(Params2::new(params));
622        assert!(s.is_ok());
623
624        let s: Result<(String, ()), de::value::Error> = Deserialize::deserialize(Params2::new(params));
625        assert!(s.is_ok());
626    }
627
628    #[test]
629    fn test_extract_path_single() {
630        let service = Router::new()
631            .insert("/name/:value/", fn_service(handler))
632            .call(())
633            .now_or_panic()
634            .unwrap();
635
636        let mut req = crate::http::WebRequest::default();
637        *req.uri_mut() = Uri::from_static("/name/47/");
638
639        let res = service.call(req).now_or_panic().unwrap();
640        let params = res.body().params();
641
642        let i: i8 = Deserialize::deserialize(Params2::new(params)).unwrap();
643        assert_eq!(i, 47);
644
645        let i: (i8,) = Deserialize::deserialize(Params2::new(params)).unwrap();
646        assert_eq!(i, (47,));
647
648        let i: Result<(i8, i8), _> = Deserialize::deserialize(Params2::new(params));
649        assert!(i.is_err());
650
651        #[derive(Deserialize)]
652        struct Test(i8);
653        let i: Test = Deserialize::deserialize(Params2::new(params)).unwrap();
654        assert_eq!(i.0, 47);
655    }
656
657    #[test]
658    fn test_extract_enum() {
659        let service = Router::new()
660            .insert("/:val/", fn_service(handler))
661            .call(())
662            .now_or_panic()
663            .unwrap();
664
665        let mut req = crate::http::WebRequest::default();
666        *req.uri_mut() = Uri::from_static("/val1/");
667
668        let res = service.call(req).now_or_panic().unwrap();
669        let params = res.body().params();
670
671        let i: TestEnum = de::Deserialize::deserialize(Params2::new(params)).unwrap();
672        assert_eq!(i, TestEnum::Val1);
673
674        // let service = Router::new()
675        //     .insert("/:val1/:val2/", fn_service(handler))
676        //     .call(())
677        //     .now_or_panic()
678        //     .unwrap();
679        //
680        // let req = http::Request::builder()
681        //     .uri("/val1/")
682        //     .body(())
683        //     .unwrap()
684        //     .map(|_| RequestExt::<()>::default());
685        //
686        // let res = service.call(req).now_or_panic().unwrap();
687        // let params = res.body().params();
688        //
689        // let i: (TestEnum, TestEnum) = de::Deserialize::deserialize(Params2::new(params)).unwrap();
690        // assert_eq!(i, (TestEnum::Val1, TestEnum::Val2));
691    }
692
693    #[test]
694    fn test_extract_errors() {
695        let service = Router::new()
696            .insert("/:value/", fn_service(handler))
697            .insert("/", fn_service(handler))
698            .call(())
699            .now_or_panic()
700            .unwrap();
701
702        let mut req = crate::http::WebRequest::default();
703        *req.uri_mut() = Uri::from_static("/name/");
704
705        let res = service.call(req).now_or_panic().unwrap();
706        let params = res.body().params();
707
708        let s: Result<Test1, de::value::Error> = Deserialize::deserialize(Params2::new(params));
709        assert!(s.is_err());
710        assert!(format!("{s:?}").contains("wrong number of parameters"));
711
712        let s: Result<Test2, de::value::Error> = Deserialize::deserialize(Params2::new(params));
713        assert!(s.is_err());
714        assert!(format!("{s:?}").contains("can not parse"));
715
716        let s: Result<(String, String), de::value::Error> = Deserialize::deserialize(Params2::new(params));
717        assert!(s.is_err());
718        assert!(format!("{s:?}").contains("wrong number of parameters"));
719
720        let s: Result<u32, de::value::Error> = Deserialize::deserialize(Params2::new(params));
721        assert!(s.is_err());
722        assert!(format!("{s:?}").contains("can not parse"));
723
724        #[derive(Debug, Deserialize)]
725        struct S {
726            _inner: (String,),
727        }
728        let s: Result<S, de::value::Error> = Deserialize::deserialize(Params2::new(params));
729        assert!(s.is_err());
730        assert!(format!("{s:?}").contains("missing field `_inner`"));
731
732        let req = crate::http::WebRequest::default();
733
734        let res = service.call(req).now_or_panic().unwrap();
735        let params = res.body().params();
736
737        let s: Result<&str, de::value::Error> = Deserialize::deserialize(Params2::new(params));
738        assert!(s.is_err());
739        assert!(format!("{s:?}").contains("expected at least one parameters"));
740
741        let s: Result<TestEnum, de::value::Error> = Deserialize::deserialize(Params2::new(params));
742        assert!(s.is_err());
743        assert!(format!("{s:?}").contains("expected at least one parameters"));
744    }
745
746    async fn handler2(Params(MyStruct { key, value }): Params<MyStruct>) -> &'static str {
747        assert_eq!(key, "qingling");
748        assert_eq!(value, "dagongren");
749        "996"
750    }
751
752    #[test]
753    fn from_request_extract() {
754        let mut req = crate::http::WebRequest::default();
755        *req.uri_mut() = Uri::from_static("/qingling/dagongren/");
756
757        let res = App::new()
758            .at("/:key/:value/", handler_service(handler2))
759            .finish()
760            .call(())
761            .now_or_panic()
762            .unwrap()
763            .call(req)
764            .now_or_panic()
765            .unwrap();
766
767        let s = collect_string_body(res.into_body()).now_or_panic().unwrap();
768
769        assert_eq!(s, "996");
770    }
771
772    #[derive(Deserialize)]
773    struct Meme<'a> {
774        name: &'a str,
775    }
776
777    async fn handler3(lazy: LazyParams<'_, Meme<'_>>) -> &'static str {
778        let Meme { name } = lazy.deserialize().unwrap();
779        assert_eq!(name, "doge");
780        "such dead much unoriginal"
781    }
782
783    #[test]
784    fn lazy_extract() {
785        let mut req = crate::http::WebRequest::default();
786        *req.uri_mut() = Uri::from_static("/meme/doge");
787
788        let res = App::new()
789            .at("/meme/:name", handler_service(handler3))
790            .finish()
791            .call(())
792            .now_or_panic()
793            .unwrap()
794            .call(req)
795            .now_or_panic()
796            .unwrap();
797
798        let s = collect_string_body(res.into_body()).now_or_panic().unwrap();
799
800        assert_eq!(s, "such dead much unoriginal");
801    }
802}