1use 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
32pub 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 }
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}