1#[cfg(feature = "ws")]
9pub use crate::ws;
10#[cfg(feature = "ws")]
12pub use crate::ws::WebSocketUpgrade;
13
14use crate::http::error::Error;
15use crate::http::response::Body;
16use bytes::Bytes;
17
18#[cfg(feature = "cookies")]
19use cookie::{Cookie, CookieJar};
20use hyper::header::HeaderMap;
21use hyper::{Method, StatusCode, Uri};
22use serde::de::DeserializeOwned;
23use std::convert::Infallible;
24use std::future::Future;
25
26pub trait FromRequestParts<S>: Sized + Send {
28 type Rejection: crate::http::response::IntoResponse + Send + 'static;
30
31 fn from_request_parts(
37 parts: &mut hyper::http::request::Parts,
38 state: &S,
39 ) -> Result<Self, Self::Rejection>;
40}
41
42pub trait FromRequest<S: Sync>: Sized + Send {
50 type Rejection: crate::http::response::IntoResponse + Send + 'static;
52
53 fn from_request(
59 req: hyper::Request<Body>,
60 state: &S,
61 ) -> impl Future<Output = Result<Self, Self::Rejection>> + Send;
62}
63
64pub(crate) const DEFAULT_MAX_BODY_SIZE: usize = 2 * 1024 * 1024;
74
75#[derive(Debug, Clone, Copy)]
79pub(crate) struct MaxBodySize(pub usize);
80
81pub(crate) fn max_body_size(extensions: &hyper::http::Extensions) -> usize {
82 extensions
83 .get::<MaxBodySize>()
84 .map_or(DEFAULT_MAX_BODY_SIZE, |m| m.0)
85}
86
87#[derive(Debug, Clone, Copy)]
113pub struct DefaultBodyLimit {
114 limit: Option<usize>,
116}
117
118impl DefaultBodyLimit {
119 #[must_use]
122 pub const fn max(limit: usize) -> Self {
123 Self { limit: Some(limit) }
124 }
125
126 #[must_use]
129 pub const fn disable() -> Self {
130 Self { limit: None }
131 }
132
133 pub fn into_middleware<S>(
135 self,
136 ) -> impl Fn(hyper::Request<Body>, crate::routing::middleware::Next<S>) -> BoxedResponseFuture
137 + Clone
138 + Send
139 + Sync
140 + 'static
141 where
142 S: Send + Sync + 'static,
143 {
144 let limit = self.limit.unwrap_or(usize::MAX);
145 move |mut req: hyper::Request<Body>, next: crate::routing::middleware::Next<S>| {
146 let _ = req.extensions_mut().insert(MaxBodySize(limit));
147 Box::pin(next.run(req)) as BoxedResponseFuture
148 }
149 }
150}
151
152type BoxedResponseFuture = std::pin::Pin<Box<dyn Future<Output = hyper::Response<Body>> + Send>>;
155
156pub trait FromRef<S> {
158 fn from_ref(state: &S) -> Self;
160}
161
162impl<T: Clone> FromRef<T> for T {
163 fn from_ref(state: &T) -> Self {
164 state.clone()
165 }
166}
167
168#[derive(Debug, Clone, Copy)]
170pub struct State<T>(pub T);
171
172impl<S, T> FromRequestParts<S> for State<T>
173where
174 T: FromRef<S> + Send + Sync + 'static,
175{
176 type Rejection = Infallible;
177
178 fn from_request_parts(
179 _parts: &mut hyper::http::request::Parts,
180 state: &S,
181 ) -> Result<Self, Self::Rejection> {
182 Ok(Self(T::from_ref(state)))
183 }
184}
185
186impl<S, T> FromRequest<S> for State<T>
187where
188 S: Sync,
189 T: FromRef<S> + Send + Sync + 'static,
190{
191 type Rejection = Infallible;
192
193 async fn from_request(req: hyper::Request<Body>, state: &S) -> Result<Self, Self::Rejection> {
194 let (mut parts, _) = req.into_parts();
195 Self::from_request_parts(&mut parts, state)
196 }
197}
198
199#[cfg(any(feature = "query", feature = "form"))]
201#[derive(Debug, Clone)]
202struct QueryIter<'de> {
203 input: &'de str,
204}
205
206struct CoercingCowDeserializer<'de> {
207 val: std::borrow::Cow<'de, str>,
208}
209
210impl<'de> serde::de::Deserializer<'de> for CoercingCowDeserializer<'de> {
211 type Error = serde::de::value::Error;
212
213 fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
214 where
215 V: serde::de::Visitor<'de>,
216 {
217 match self.val {
218 std::borrow::Cow::Borrowed(s) => visitor.visit_borrowed_str(s),
219 std::borrow::Cow::Owned(s) => visitor.visit_string(s),
220 }
221 }
222
223 fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
224 where
225 V: serde::de::Visitor<'de>,
226 {
227 match self.val {
228 std::borrow::Cow::Borrowed(s) => visitor.visit_borrowed_str(s),
229 std::borrow::Cow::Owned(s) => visitor.visit_string(s),
230 }
231 }
232
233 fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Self::Error>
234 where
235 V: serde::de::Visitor<'de>,
236 {
237 self.deserialize_str(visitor)
238 }
239
240 fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
241 where
242 V: serde::de::Visitor<'de>,
243 {
244 let n = self
245 .val
246 .parse::<u8>()
247 .map_err(|e| serde::de::Error::custom(e.to_string()))?;
248 visitor.visit_u8(n)
249 }
250
251 fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
252 where
253 V: serde::de::Visitor<'de>,
254 {
255 let n = self
256 .val
257 .parse::<u16>()
258 .map_err(|e| serde::de::Error::custom(e.to_string()))?;
259 visitor.visit_u16(n)
260 }
261
262 fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
263 where
264 V: serde::de::Visitor<'de>,
265 {
266 let n = self
267 .val
268 .parse::<u32>()
269 .map_err(|e| serde::de::Error::custom(e.to_string()))?;
270 visitor.visit_u32(n)
271 }
272
273 fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
274 where
275 V: serde::de::Visitor<'de>,
276 {
277 let n = self
278 .val
279 .parse::<u64>()
280 .map_err(|e| serde::de::Error::custom(e.to_string()))?;
281 visitor.visit_u64(n)
282 }
283
284 fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
285 where
286 V: serde::de::Visitor<'de>,
287 {
288 let n = self
289 .val
290 .parse::<i8>()
291 .map_err(|e| serde::de::Error::custom(e.to_string()))?;
292 visitor.visit_i8(n)
293 }
294
295 fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
296 where
297 V: serde::de::Visitor<'de>,
298 {
299 let n = self
300 .val
301 .parse::<i16>()
302 .map_err(|e| serde::de::Error::custom(e.to_string()))?;
303 visitor.visit_i16(n)
304 }
305
306 fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
307 where
308 V: serde::de::Visitor<'de>,
309 {
310 let n = self
311 .val
312 .parse::<i32>()
313 .map_err(|e| serde::de::Error::custom(e.to_string()))?;
314 visitor.visit_i32(n)
315 }
316
317 fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
318 where
319 V: serde::de::Visitor<'de>,
320 {
321 let n = self
322 .val
323 .parse::<i64>()
324 .map_err(|e| serde::de::Error::custom(e.to_string()))?;
325 visitor.visit_i64(n)
326 }
327
328 fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
329 where
330 V: serde::de::Visitor<'de>,
331 {
332 let n = self
333 .val
334 .parse::<f32>()
335 .map_err(|e| serde::de::Error::custom(e.to_string()))?;
336 visitor.visit_f32(n)
337 }
338
339 fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
340 where
341 V: serde::de::Visitor<'de>,
342 {
343 let n = self
344 .val
345 .parse::<f64>()
346 .map_err(|e| serde::de::Error::custom(e.to_string()))?;
347 visitor.visit_f64(n)
348 }
349
350 fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
351 where
352 V: serde::de::Visitor<'de>,
353 {
354 let b = match self.val.as_ref() {
355 "true" | "1" => true,
356 "false" | "0" => false,
357 _ => self
358 .val
359 .parse::<bool>()
360 .map_err(|e| serde::de::Error::custom(e.to_string()))?,
361 };
362 visitor.visit_bool(b)
363 }
364
365 fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
366 where
367 V: serde::de::Visitor<'de>,
368 {
369 visitor.visit_some(self)
370 }
371
372 fn deserialize_enum<V>(
373 self,
374 _name: &'static str,
375 _variants: &'static [&'static str],
376 visitor: V,
377 ) -> Result<V::Value, Self::Error>
378 where
379 V: serde::de::Visitor<'de>,
380 {
381 use serde::de::IntoDeserializer;
382 visitor.visit_enum(self.val.into_deserializer())
383 }
384
385 serde::forward_to_deserialize_any! {
386 char bytes byte_buf unit unit_struct newtype_struct
387 seq tuple tuple_struct map struct identifier ignored_any
388 }
389}
390
391impl<'de> serde::de::IntoDeserializer<'de, serde::de::value::Error>
392 for CoercingCowDeserializer<'de>
393{
394 type Deserializer = Self;
395 fn into_deserializer(self) -> Self {
396 self
397 }
398}
399
400#[cfg(any(feature = "query", feature = "form"))]
401impl<'de> Iterator for QueryIter<'de> {
402 type Item = (std::borrow::Cow<'de, str>, CoercingCowDeserializer<'de>);
403
404 fn next(&mut self) -> Option<Self::Item> {
405 if self.input.is_empty() {
406 return None;
407 }
408
409 let bytes = self.input.as_bytes();
410 let len = bytes.len();
411 let end = bytes.iter().position(|&b| b == b'&').unwrap_or(len);
412 let pair_str = &self.input[..end];
413
414 if end < len {
415 self.input = &self.input[end + 1..];
416 } else {
417 self.input = "";
418 }
419
420 if pair_str.is_empty() {
421 return self.next();
422 }
423
424 let pair_bytes = pair_str.as_bytes();
425 let (key_raw, val_raw) = pair_bytes
426 .iter()
427 .position(|&b| b == b'=')
428 .map_or((pair_str, ""), |eq_idx| {
429 (&pair_str[..eq_idx], &pair_str[eq_idx + 1..])
430 });
431
432 let key = decode_query_param(key_raw);
433 let val = decode_query_param(val_raw);
434 Some((key, CoercingCowDeserializer { val }))
435 }
436}
437
438#[cfg(any(feature = "query", feature = "form"))]
439fn decode_query_param(s: &str) -> std::borrow::Cow<'_, str> {
440 let bytes = s.as_bytes();
441 if !bytes.iter().any(|&b| b == b'%' || b == b'+') {
442 return std::borrow::Cow::Borrowed(s);
443 }
444
445 let mut decoded = Vec::with_capacity(bytes.len());
446 let mut i = 0;
447 while i < bytes.len() {
448 match bytes[i] {
449 b'%' if i + 2 < bytes.len() => {
450 if let Ok(hex) = std::str::from_utf8(&bytes[i + 1..i + 3])
451 && let Ok(val) = u8::from_str_radix(hex, 16)
452 {
453 decoded.push(val);
454 i += 3;
455 continue;
456 }
457 decoded.push(b'%');
458 i += 1;
459 }
460 b'+' => {
461 decoded.push(b' ');
462 i += 1;
463 }
464 b => {
465 decoded.push(b);
466 i += 1;
467 }
468 }
469 }
470 String::from_utf8(decoded)
471 .map_or_else(|_| std::borrow::Cow::Borrowed(s), std::borrow::Cow::Owned)
472}
473
474#[derive(Debug, Clone)]
485pub struct Path<T>(pub T);
486
487#[derive(Debug, Clone)]
489pub struct PathParams(pub Vec<(std::sync::Arc<str>, String)>);
490
491struct PathDeserializer<'de> {
495 params: &'de [(std::sync::Arc<str>, String)],
496}
497
498impl<'de> PathDeserializer<'de> {
499 fn single_value(&self) -> Result<&'de str, serde::de::value::Error> {
500 match self.params {
501 [(_, v)] => Ok(v.as_str()),
502 _ => Err(serde::de::Error::custom(format!(
503 "wrong number of path parameters: expected 1, got {}",
504 self.params.len()
505 ))),
506 }
507 }
508
509 const fn value_deserializer(val: &'de str) -> CoercingCowDeserializer<'de> {
510 CoercingCowDeserializer {
511 val: std::borrow::Cow::Borrowed(val),
512 }
513 }
514
515 fn map_deserializer(
516 &self,
517 ) -> serde::de::value::MapDeserializer<
518 'de,
519 impl Iterator<Item = (std::borrow::Cow<'de, str>, CoercingCowDeserializer<'de>)>,
520 serde::de::value::Error,
521 > {
522 serde::de::value::MapDeserializer::new(self.params.iter().map(|(k, v)| {
523 (
524 std::borrow::Cow::Borrowed(k.as_ref()),
525 CoercingCowDeserializer {
526 val: std::borrow::Cow::Borrowed(v.as_str()),
527 },
528 )
529 }))
530 }
531}
532
533struct PathParamsSeqAccess<'de> {
534 iter: std::slice::Iter<'de, (std::sync::Arc<str>, String)>,
535}
536
537impl<'de> serde::de::SeqAccess<'de> for PathParamsSeqAccess<'de> {
538 type Error = serde::de::value::Error;
539
540 fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
541 where
542 T: serde::de::DeserializeSeed<'de>,
543 {
544 match self.iter.next() {
545 Some((_, v)) => seed
546 .deserialize(CoercingCowDeserializer {
547 val: std::borrow::Cow::Borrowed(v.as_str()),
548 })
549 .map(Some),
550 None => Ok(None),
551 }
552 }
553
554 fn size_hint(&self) -> Option<usize> {
555 Some(self.iter.len())
556 }
557}
558
559macro_rules! path_deserialize_scalar {
560 ($($method:ident),* $(,)?) => {
561 $(
562 fn $method<V>(self, visitor: V) -> Result<V::Value, Self::Error>
563 where
564 V: serde::de::Visitor<'de>,
565 {
566 let val = self.single_value()?;
567 PathDeserializer::value_deserializer(val).$method(visitor)
568 }
569 )*
570 };
571}
572
573impl<'de> serde::de::Deserializer<'de> for PathDeserializer<'de> {
574 type Error = serde::de::value::Error;
575
576 fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
577 where
578 V: serde::de::Visitor<'de>,
579 {
580 visitor.visit_map(self.map_deserializer())
584 }
585
586 path_deserialize_scalar!(
587 deserialize_bool,
588 deserialize_u8,
589 deserialize_u16,
590 deserialize_u32,
591 deserialize_u64,
592 deserialize_i8,
593 deserialize_i16,
594 deserialize_i32,
595 deserialize_i64,
596 deserialize_f32,
597 deserialize_f64,
598 deserialize_char,
599 deserialize_str,
600 deserialize_string,
601 deserialize_bytes,
602 deserialize_byte_buf,
603 );
604
605 fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
606 where
607 V: serde::de::Visitor<'de>,
608 {
609 visitor.visit_some(self)
610 }
611
612 fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
613 where
614 V: serde::de::Visitor<'de>,
615 {
616 visitor.visit_unit()
617 }
618
619 fn deserialize_unit_struct<V>(
620 self,
621 _name: &'static str,
622 visitor: V,
623 ) -> Result<V::Value, Self::Error>
624 where
625 V: serde::de::Visitor<'de>,
626 {
627 visitor.visit_unit()
628 }
629
630 fn deserialize_newtype_struct<V>(
631 self,
632 _name: &'static str,
633 visitor: V,
634 ) -> Result<V::Value, Self::Error>
635 where
636 V: serde::de::Visitor<'de>,
637 {
638 visitor.visit_newtype_struct(self)
639 }
640
641 fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
642 where
643 V: serde::de::Visitor<'de>,
644 {
645 visitor.visit_seq(PathParamsSeqAccess {
646 iter: self.params.iter(),
647 })
648 }
649
650 fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value, Self::Error>
651 where
652 V: serde::de::Visitor<'de>,
653 {
654 if self.params.len() != len {
655 return Err(serde::de::Error::custom(format!(
656 "wrong number of path parameters: expected {len}, got {}",
657 self.params.len()
658 )));
659 }
660 self.deserialize_seq(visitor)
661 }
662
663 fn deserialize_tuple_struct<V>(
664 self,
665 _name: &'static str,
666 len: usize,
667 visitor: V,
668 ) -> Result<V::Value, Self::Error>
669 where
670 V: serde::de::Visitor<'de>,
671 {
672 self.deserialize_tuple(len, visitor)
673 }
674
675 fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
676 where
677 V: serde::de::Visitor<'de>,
678 {
679 visitor.visit_map(self.map_deserializer())
680 }
681
682 fn deserialize_struct<V>(
683 self,
684 _name: &'static str,
685 _fields: &'static [&'static str],
686 visitor: V,
687 ) -> Result<V::Value, Self::Error>
688 where
689 V: serde::de::Visitor<'de>,
690 {
691 self.deserialize_map(visitor)
692 }
693
694 fn deserialize_enum<V>(
695 self,
696 _name: &'static str,
697 _variants: &'static [&'static str],
698 visitor: V,
699 ) -> Result<V::Value, Self::Error>
700 where
701 V: serde::de::Visitor<'de>,
702 {
703 use serde::de::IntoDeserializer;
704 let val = self.single_value()?;
705 visitor.visit_enum(val.into_deserializer())
706 }
707
708 fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value, Self::Error>
709 where
710 V: serde::de::Visitor<'de>,
711 {
712 self.deserialize_str(visitor)
713 }
714
715 fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
716 where
717 V: serde::de::Visitor<'de>,
718 {
719 visitor.visit_unit()
720 }
721}
722
723impl<S, T> FromRequestParts<S> for Path<T>
724where
725 T: DeserializeOwned + Send + Sync + 'static,
726{
727 type Rejection = Error;
728
729 fn from_request_parts(
730 parts: &mut hyper::http::request::Parts,
731 _state: &S,
732 ) -> Result<Self, Self::Rejection> {
733 let params = parts
739 .extensions
740 .get::<PathParams>()
741 .map_or(&[][..], |p| p.0.as_slice());
742
743 T::deserialize(PathDeserializer { params })
744 .map(Path)
745 .map_err(|e: serde::de::value::Error| Error::Rejection {
746 status: StatusCode::BAD_REQUEST,
747 message: format!("Failed to deserialize path parameters: {e}"),
748 })
749 }
750}
751
752impl<S, T> FromRequest<S> for Path<T>
753where
754 S: Sync,
755 T: DeserializeOwned + Send + Sync + 'static,
756{
757 type Rejection = Error;
758
759 async fn from_request(req: hyper::Request<Body>, state: &S) -> Result<Self, Self::Rejection> {
760 let (mut parts, _) = req.into_parts();
761 Self::from_request_parts(&mut parts, state)
762 }
763}
764
765#[cfg(feature = "query")]
767#[derive(Debug, Clone)]
768pub struct Query<T>(pub T);
769
770#[cfg(feature = "query")]
771impl<S, T> FromRequestParts<S> for Query<T>
772where
773 T: DeserializeOwned + Send + Sync + 'static,
774{
775 type Rejection = Error;
776
777 fn from_request_parts(
778 parts: &mut hyper::http::request::Parts,
779 _state: &S,
780 ) -> Result<Self, Self::Rejection> {
781 let query_str = parts.uri.query().unwrap_or("");
782 let iter = QueryIter { input: query_str };
783 let map_de = serde::de::value::MapDeserializer::new(iter);
784 T::deserialize(map_de)
785 .map(Query)
786 .map_err(|e: serde::de::value::Error| Error::Rejection {
787 status: StatusCode::BAD_REQUEST,
788 message: format!("Failed to deserialize query parameters: {e}"),
789 })
790 }
791}
792
793#[cfg(feature = "query")]
794impl<S, T> FromRequest<S> for Query<T>
795where
796 S: Sync,
797 T: DeserializeOwned + Send + Sync + 'static,
798{
799 type Rejection = Error;
800
801 async fn from_request(req: hyper::Request<Body>, state: &S) -> Result<Self, Self::Rejection> {
802 let (mut parts, _) = req.into_parts();
803 Self::from_request_parts(&mut parts, state)
804 }
805}
806
807#[derive(Debug, Clone)]
811pub struct RawQuery(pub Option<String>);
812
813impl<S> FromRequestParts<S> for RawQuery {
814 type Rejection = std::convert::Infallible;
815
816 fn from_request_parts(
817 parts: &mut hyper::http::request::Parts,
818 _state: &S,
819 ) -> Result<Self, Self::Rejection> {
820 Ok(Self(parts.uri.query().map(str::to_string)))
821 }
822}
823
824#[cfg(feature = "json")]
828fn is_json_content_type(content_type: &str) -> bool {
829 let essence = content_type.split(';').next().unwrap_or("").trim();
830 let Some((ty, subtype)) = essence.split_once('/') else {
831 return false;
832 };
833 if !ty.eq_ignore_ascii_case("application") {
834 return false;
835 }
836 subtype.eq_ignore_ascii_case("json") || subtype.to_ascii_lowercase().ends_with("+json")
837}
838
839#[cfg(feature = "json")]
841#[derive(Debug, Clone)]
842pub struct Json<T>(pub T);
843
844#[cfg(feature = "json")]
845impl<S, T> FromRequest<S> for Json<T>
846where
847 S: Sync,
848 T: DeserializeOwned + Send + Sync + 'static,
849{
850 type Rejection = Error;
851
852 async fn from_request(req: hyper::Request<Body>, _state: &S) -> Result<Self, Self::Rejection> {
853 let ct = req
856 .headers()
857 .get(hyper::header::CONTENT_TYPE)
858 .and_then(|v| v.to_str().ok())
859 .unwrap_or("");
860 if !is_json_content_type(ct) {
861 return Err(Error::Rejection {
862 status: StatusCode::UNSUPPORTED_MEDIA_TYPE,
863 message: format!("Expected Content-Type: application/json, got: '{ct}'"),
864 });
865 }
866 let limit = max_body_size(req.extensions());
867 let body = req.into_body().collect_bytes(limit).await?;
868 serde_json::from_slice::<T>(&body).map(Json).map_err(|e| {
869 let status = match e.classify() {
875 serde_json::error::Category::Syntax | serde_json::error::Category::Eof => {
876 StatusCode::BAD_REQUEST
877 }
878 serde_json::error::Category::Data | serde_json::error::Category::Io => {
879 StatusCode::UNPROCESSABLE_ENTITY
880 }
881 };
882 Error::Rejection {
883 status,
884 message: format!("Failed to deserialize JSON payload: {e}"),
885 }
886 })
887 }
888}
889
890impl<S> FromRequestParts<S> for HeaderMap {
891 type Rejection = Infallible;
892
893 fn from_request_parts(
894 parts: &mut hyper::http::request::Parts,
895 _state: &S,
896 ) -> Result<Self, Self::Rejection> {
897 Ok(parts.headers.clone())
898 }
899}
900
901impl<S> FromRequestParts<S> for Method {
902 type Rejection = Infallible;
903
904 fn from_request_parts(
905 parts: &mut hyper::http::request::Parts,
906 _state: &S,
907 ) -> Result<Self, Self::Rejection> {
908 Ok(parts.method.clone())
909 }
910}
911
912impl<S> FromRequestParts<S> for Uri {
913 type Rejection = Infallible;
914
915 fn from_request_parts(
916 parts: &mut hyper::http::request::Parts,
917 _state: &S,
918 ) -> Result<Self, Self::Rejection> {
919 Ok(parts.uri.clone())
920 }
921}
922
923impl<S: Sync> FromRequest<S> for Bytes {
924 type Rejection = Error;
925
926 async fn from_request(req: hyper::Request<Body>, _state: &S) -> Result<Self, Self::Rejection> {
927 let limit = max_body_size(req.extensions());
928 req.into_body().collect_bytes(limit).await
929 }
930}
931
932impl<S: Sync> FromRequest<S> for String {
933 type Rejection = Error;
934
935 async fn from_request(req: hyper::Request<Body>, _state: &S) -> Result<Self, Self::Rejection> {
936 let limit = max_body_size(req.extensions());
937 let body = req.into_body().collect_bytes(limit).await?;
938 Self::from_utf8(body.to_vec()).map_err(|e| Error::Rejection {
939 status: StatusCode::BAD_REQUEST,
940 message: format!("Request body is not valid UTF-8: {e}"),
941 })
942 }
943}
944
945#[cfg(feature = "form")]
947#[derive(Debug, Clone)]
948pub struct Form<T>(pub T);
949
950#[cfg(feature = "form")]
951impl<S, T> FromRequestParts<S> for Form<T>
952where
953 T: DeserializeOwned + Send + Sync + 'static,
954{
955 type Rejection = Error;
956
957 fn from_request_parts(
961 parts: &mut hyper::http::request::Parts,
962 _state: &S,
963 ) -> Result<Self, Self::Rejection> {
964 let query_str = parts.uri.query().unwrap_or("");
965 let iter = QueryIter { input: query_str };
966 let map_de = serde::de::value::MapDeserializer::new(iter);
967 T::deserialize(map_de)
968 .map(Form)
969 .map_err(|e: serde::de::value::Error| Error::Rejection {
970 status: StatusCode::UNPROCESSABLE_ENTITY,
971 message: format!("Failed to deserialize form payload: {e}"),
972 })
973 }
974}
975
976#[cfg(feature = "form")]
977impl<S, T> FromRequest<S> for Form<T>
978where
979 S: Sync,
980 T: DeserializeOwned + Send + Sync + 'static,
981{
982 type Rejection = Error;
983
984 async fn from_request(req: hyper::Request<Body>, state: &S) -> Result<Self, Self::Rejection> {
985 if req.method() == hyper::Method::GET || req.method() == hyper::Method::HEAD {
989 let (mut parts, _body) = req.into_parts();
990 return Self::from_request_parts(&mut parts, state);
991 }
992
993 let ct = req
995 .headers()
996 .get(hyper::header::CONTENT_TYPE)
997 .and_then(|v| v.to_str().ok())
998 .unwrap_or("");
999 let essence = ct.split(';').next().unwrap_or("").trim();
1000 if !essence.eq_ignore_ascii_case("application/x-www-form-urlencoded") {
1001 return Err(Error::Rejection {
1002 status: StatusCode::UNSUPPORTED_MEDIA_TYPE,
1003 message: format!(
1004 "Expected Content-Type: application/x-www-form-urlencoded, got: '{ct}'"
1005 ),
1006 });
1007 }
1008 let limit = max_body_size(req.extensions());
1009 let body = req.into_body().collect_bytes(limit).await?;
1010 let body_str = std::str::from_utf8(&body).map_err(|_| Error::Rejection {
1011 status: StatusCode::BAD_REQUEST,
1012 message: "Form body is not valid UTF-8".to_string(),
1013 })?;
1014 let iter = QueryIter { input: body_str };
1015 let map_de = serde::de::value::MapDeserializer::new(iter);
1016 T::deserialize(map_de)
1017 .map(Form)
1018 .map_err(|e: serde::de::value::Error| Error::Rejection {
1019 status: StatusCode::UNPROCESSABLE_ENTITY,
1020 message: format!("Failed to deserialize form payload: {e}"),
1021 })
1022 }
1023}
1024
1025#[derive(Debug, Clone, Copy)]
1027pub struct Extension<T>(pub T);
1028
1029impl<S, T> FromRequestParts<S> for Extension<T>
1030where
1031 T: Clone + Send + Sync + 'static,
1032{
1033 type Rejection = Error;
1034
1035 fn from_request_parts(
1036 parts: &mut hyper::http::request::Parts,
1037 _state: &S,
1038 ) -> Result<Self, Self::Rejection> {
1039 parts
1040 .extensions
1041 .get::<T>()
1042 .cloned()
1043 .map(Extension)
1044 .ok_or_else(|| Error::Rejection {
1045 status: StatusCode::INTERNAL_SERVER_ERROR,
1046 message: format!("Missing extension: {}", std::any::type_name::<T>()),
1047 })
1048 }
1049}
1050
1051impl<S, T> FromRequest<S> for Extension<T>
1052where
1053 S: Sync,
1054 T: Clone + Send + Sync + 'static,
1055{
1056 type Rejection = Error;
1057
1058 async fn from_request(req: hyper::Request<Body>, state: &S) -> Result<Self, Self::Rejection> {
1059 let (mut parts, _) = req.into_parts();
1060 Self::from_request_parts(&mut parts, state)
1061 }
1062}
1063
1064#[cfg(feature = "cookies")]
1066#[derive(Debug, Clone)]
1067pub struct Cookies {
1068 pub jar: CookieJar,
1070}
1071
1072#[cfg(feature = "cookies")]
1073impl Cookies {
1074 #[must_use]
1076 pub fn new() -> Self {
1077 Self {
1078 jar: CookieJar::new(),
1079 }
1080 }
1081
1082 #[must_use]
1084 pub fn get(&self, name: &str) -> Option<&Cookie<'static>> {
1085 self.jar.get(name)
1086 }
1087
1088 #[allow(clippy::should_implement_trait)]
1097 #[must_use]
1098 pub fn add(mut self, cookie: Cookie<'static>) -> Self {
1099 self.jar.add(cookie);
1100 self
1101 }
1102
1103 #[must_use]
1106 pub fn remove(mut self, cookie: Cookie<'static>) -> Self {
1107 self.jar.remove(cookie);
1108 self
1109 }
1110}
1111
1112#[cfg(feature = "cookies")]
1113impl Default for Cookies {
1114 fn default() -> Self {
1115 Self::new()
1116 }
1117}
1118
1119#[cfg(feature = "cookies")]
1120impl<S> FromRequestParts<S> for Cookies {
1121 type Rejection = Infallible;
1122
1123 fn from_request_parts(
1124 parts: &mut hyper::http::request::Parts,
1125 _state: &S,
1126 ) -> Result<Self, Self::Rejection> {
1127 let mut jar = CookieJar::new();
1128 if let Some(cookie_header) = parts.headers.get(hyper::header::COOKIE)
1129 && let Ok(cookie_str) = cookie_header.to_str()
1130 {
1131 for c in Cookie::split_parse_encoded(cookie_str).flatten() {
1132 jar.add_original(c.into_owned());
1133 }
1134 }
1135 Ok(Self { jar })
1136 }
1137}
1138
1139impl<S: Sync> FromRequest<S> for hyper::Request<Bytes> {
1140 type Rejection = Error;
1141
1142 async fn from_request(req: hyper::Request<Body>, _state: &S) -> Result<Self, Self::Rejection> {
1143 let limit = max_body_size(req.extensions());
1144 let (parts, body) = req.into_parts();
1145 let bytes = body.collect_bytes(limit).await?;
1146 Ok(Self::from_parts(parts, bytes))
1147 }
1148}
1149
1150#[derive(Debug)]
1158pub struct BodyStream(pub Body);
1159
1160impl<S: Sync> FromRequest<S> for BodyStream {
1161 type Rejection = Infallible;
1162
1163 async fn from_request(req: hyper::Request<Body>, _state: &S) -> Result<Self, Self::Rejection> {
1164 Ok(Self(req.into_body()))
1165 }
1166}
1167
1168impl<S: Sync> FromRequest<S> for hyper::Request<Body> {
1169 type Rejection = Infallible;
1170
1171 async fn from_request(req: hyper::Request<Body>, _state: &S) -> Result<Self, Self::Rejection> {
1172 Ok(req)
1173 }
1174}
1175
1176#[derive(Debug, Clone)]
1178pub struct Host(pub String);
1179
1180impl<S> FromRequestParts<S> for Host {
1181 type Rejection = Error;
1182
1183 fn from_request_parts(
1184 parts: &mut hyper::http::request::Parts,
1185 _state: &S,
1186 ) -> Result<Self, Self::Rejection> {
1187 if let Some(host) = parts
1188 .headers
1189 .get(hyper::header::HOST)
1190 .and_then(|h| h.to_str().ok())
1191 {
1192 Ok(Self(host.to_string()))
1193 } else if let Some(host) = parts.uri.host() {
1194 Ok(Self(host.to_string()))
1195 } else {
1196 Err(Error::Rejection {
1197 status: StatusCode::BAD_REQUEST,
1198 message: "Missing Host header or authority in URI".to_string(),
1199 })
1200 }
1201 }
1202}
1203
1204#[cfg(feature = "original-uri")]
1206#[derive(Debug, Clone)]
1207pub struct OriginalUri(pub Uri);
1208
1209#[cfg(feature = "original-uri")]
1210impl<S> FromRequestParts<S> for OriginalUri {
1211 type Rejection = Infallible;
1212
1213 fn from_request_parts(
1214 parts: &mut hyper::http::request::Parts,
1215 _state: &S,
1216 ) -> Result<Self, Self::Rejection> {
1217 let uri = parts
1218 .extensions
1219 .get::<Self>()
1220 .map_or_else(|| parts.uri.clone(), |ou| ou.0.clone());
1221 Ok(Self(uri))
1222 }
1223}
1224
1225#[cfg(feature = "matched-path")]
1234#[derive(Debug, Clone)]
1235pub struct MatchedPath(pub(crate) std::sync::Arc<str>);
1236
1237#[cfg(feature = "matched-path")]
1238impl MatchedPath {
1239 #[must_use]
1241 pub fn as_str(&self) -> &str {
1242 &self.0
1243 }
1244}
1245
1246#[cfg(feature = "matched-path")]
1247impl<S> FromRequestParts<S> for MatchedPath {
1248 type Rejection = Error;
1249
1250 fn from_request_parts(
1251 parts: &mut hyper::http::request::Parts,
1252 _state: &S,
1253 ) -> Result<Self, Self::Rejection> {
1254 parts
1255 .extensions
1256 .get::<Self>()
1257 .cloned()
1258 .ok_or_else(|| Error::Rejection {
1259 status: StatusCode::INTERNAL_SERVER_ERROR,
1260 message: "No matched path found in request extensions".to_string(),
1261 })
1262 }
1263}
1264
1265#[derive(Debug, Clone, Copy)]
1267pub struct ConnectInfo<T>(pub T);
1268
1269impl<S, T> FromRequestParts<S> for ConnectInfo<T>
1270where
1271 T: Clone + Send + Sync + 'static,
1272{
1273 type Rejection = Error;
1274
1275 fn from_request_parts(
1276 parts: &mut hyper::http::request::Parts,
1277 _state: &S,
1278 ) -> Result<Self, Self::Rejection> {
1279 parts
1280 .extensions
1281 .get::<Self>()
1282 .cloned()
1283 .ok_or_else(|| Error::Rejection {
1284 status: StatusCode::INTERNAL_SERVER_ERROR,
1285 message: format!(
1286 "Missing ConnectInfo<{}> extension",
1287 std::any::type_name::<T>()
1288 ),
1289 })
1290 }
1291}
1292
1293impl<S, T> FromRequest<S> for ConnectInfo<T>
1294where
1295 S: Sync,
1296 T: Clone + Send + Sync + 'static,
1297{
1298 type Rejection = Error;
1299
1300 async fn from_request(req: hyper::Request<Body>, state: &S) -> Result<Self, Self::Rejection> {
1301 let (mut parts, _) = req.into_parts();
1302 Self::from_request_parts(&mut parts, state)
1303 }
1304}
1305
1306macro_rules! impl_from_request_via_parts {
1307 ($ty:ty) => {
1308 impl<S: Sync> FromRequest<S> for $ty {
1309 type Rejection = <Self as FromRequestParts<S>>::Rejection;
1310
1311 async fn from_request(
1312 req: hyper::Request<Body>,
1313 state: &S,
1314 ) -> Result<Self, Self::Rejection> {
1315 let (mut parts, _) = req.into_parts();
1316 <Self as FromRequestParts<S>>::from_request_parts(&mut parts, state)
1317 }
1318 }
1319 };
1320}
1321
1322impl_from_request_via_parts!(RawQuery);
1323impl_from_request_via_parts!(HeaderMap);
1324impl_from_request_via_parts!(Method);
1325impl_from_request_via_parts!(Uri);
1326#[cfg(feature = "cookies")]
1327impl_from_request_via_parts!(Cookies);
1328impl_from_request_via_parts!(Host);
1329#[cfg(feature = "original-uri")]
1330impl_from_request_via_parts!(OriginalUri);
1331#[cfg(feature = "matched-path")]
1332impl_from_request_via_parts!(MatchedPath);
1333
1334#[cfg(test)]
1335mod tests {
1336 #![allow(clippy::unwrap_used)]
1337 use super::*;
1338 use hyper::http::Request;
1339 use serde::Deserialize;
1340
1341 #[derive(Deserialize, Debug)]
1342 #[allow(clippy::struct_excessive_bools)]
1343 struct BigCoerce {
1344 a: u16,
1345 b: u64,
1346 c: i8,
1347 d: i16,
1348 e: i32,
1349 f: i64,
1350 g: f32,
1351 h: f64,
1352 i: bool,
1353 j: bool,
1354 k: bool,
1355 l: bool,
1356 }
1357
1358 #[derive(Deserialize)]
1359 #[allow(dead_code)]
1360 struct BoolTest {
1361 val: bool,
1362 }
1363
1364 #[derive(Deserialize, PartialEq, Debug)]
1365 enum Color {
1366 Red,
1367 Blue,
1368 }
1369
1370 #[derive(Deserialize)]
1371 struct EnumTest {
1372 val: Color,
1373 }
1374
1375 #[cfg(any(feature = "query", feature = "form"))]
1376 #[test]
1377 fn test_coercing_cow_deserializer() {
1378 let query_str = "a=12&b=34&c=5&d=6&e=7&f=8&g=1.2&h=3.4&i=true&j=1&k=false&l=0";
1379 let iter = QueryIter { input: query_str };
1380 let map_de = serde::de::value::MapDeserializer::new(iter);
1381 let data = BigCoerce::deserialize(map_de).unwrap();
1382 assert_eq!(data.a, 12);
1383 assert_eq!(data.b, 34);
1384 assert_eq!(data.c, 5);
1385 assert_eq!(data.d, 6);
1386 assert_eq!(data.e, 7);
1387 assert_eq!(data.f, 8);
1388 assert!((data.g - 1.2).abs() < 0.001);
1389 assert!((data.h - 3.4).abs() < 0.001);
1390 assert!(data.i);
1391 assert!(data.j);
1392 assert!(!data.k);
1393 assert!(!data.l);
1394
1395 let iter = QueryIter {
1397 input: "val=not_bool",
1398 };
1399 let map_de = serde::de::value::MapDeserializer::new(iter);
1400 assert!(BoolTest::deserialize(map_de).is_err());
1401
1402 let iter = QueryIter { input: "val=Red" };
1404 let map_de = serde::de::value::MapDeserializer::new(iter);
1405 let et = EnumTest::deserialize(map_de).unwrap();
1406 assert_eq!(et.val, Color::Red);
1407 }
1408
1409 #[cfg(any(feature = "query", feature = "form"))]
1410 #[test]
1411 fn test_query_iter_edge_cases() {
1412 let query_str = "&&foo&&bar=baz";
1414 let mut iter = QueryIter { input: query_str };
1415 let first = iter.next().unwrap();
1416 assert_eq!(first.0, "foo");
1417 assert_eq!(first.1.val, "");
1418 let second = iter.next().unwrap();
1419 assert_eq!(second.0, "bar");
1420 assert_eq!(second.1.val, "baz");
1421
1422 let query_str2 = "foo=bar%xy&baz=%";
1424 let mut iter2 = QueryIter { input: query_str2 };
1425 let first2 = iter2.next().unwrap();
1426 assert_eq!(first2.0, "foo");
1427 assert_eq!(first2.1.val, "bar%xy");
1428 let second2 = iter2.next().unwrap();
1429 assert_eq!(second2.0, "baz");
1430 assert_eq!(second2.1.val, "%");
1431 }
1432
1433 #[tokio::test]
1434 async fn test_extractors_direct() {
1435 let req = Request::builder()
1436 .method("POST")
1437 .uri("/path?q=1")
1438 .header("x-test", "hello")
1439 .body(Body::full(Bytes::from("body_bytes")))
1440 .unwrap();
1441 let (mut parts, body) = req.into_parts();
1442
1443 let headers = HeaderMap::from_request_parts(&mut parts, &()).unwrap();
1445 assert_eq!(headers.get("x-test").unwrap(), "hello");
1446
1447 let method = Method::from_request_parts(&mut parts, &()).unwrap();
1449 assert_eq!(method, "POST");
1450
1451 let uri = Uri::from_request_parts(&mut parts, &()).unwrap();
1453 assert_eq!(uri.path(), "/path");
1454
1455 let req_bytes = Request::from_parts(parts.clone(), Body::full(Bytes::from("body_bytes")));
1457 let bytes = Bytes::from_request(req_bytes, &()).await.unwrap();
1458 assert_eq!(bytes.as_ref(), b"body_bytes");
1459
1460 let req_full = Request::from_parts(parts, body);
1462 let extracted_req = <Request<Bytes>>::from_request(req_full, &()).await.unwrap();
1463 assert_eq!(extracted_req.uri().path(), "/path");
1464 }
1465
1466 #[cfg(feature = "cookies")]
1467 #[test]
1468 fn test_cookies_remove() {
1469 use cookie::Cookie;
1470 let cookies = Cookies::new().add(Cookie::new("foo", "bar"));
1471 assert_eq!(cookies.get("foo").unwrap().value(), "bar");
1472 let cookies = cookies.remove(Cookie::new("foo", ""));
1473 assert!(cookies.get("foo").is_none());
1474 }
1475
1476 #[test]
1477 fn test_host_missing() {
1478 let mut parts = Request::builder().uri("/").body(()).unwrap().into_parts().0;
1479 let res = Host::from_request_parts(&mut parts, &());
1480 assert!(res.is_err());
1481 }
1482
1483 #[test]
1484 fn test_connect_info_missing() {
1485 let mut parts = Request::builder().uri("/").body(()).unwrap().into_parts().0;
1486 let res = ConnectInfo::<std::net::SocketAddr>::from_request_parts(&mut parts, &());
1487 assert!(res.is_err());
1488 }
1489
1490 #[cfg(feature = "form")]
1491 #[tokio::test]
1492 async fn test_form_errors() {
1493 #[derive(Deserialize, Debug)]
1494 #[allow(dead_code)]
1495 struct FormPayload {
1496 foo: String,
1497 }
1498
1499 let req = Request::builder()
1506 .method("POST")
1507 .header(hyper::header::CONTENT_TYPE, "text/plain")
1508 .body(Body::full(Bytes::from("foo=bar")))
1509 .unwrap();
1510 let res = Form::<FormPayload>::from_request(req, &()).await;
1511 assert!(res.is_err());
1512
1513 let utf8_req = Request::builder()
1515 .method("POST")
1516 .header(
1517 hyper::header::CONTENT_TYPE,
1518 "application/x-www-form-urlencoded",
1519 )
1520 .body(Body::full(Bytes::from(vec![0xff, 0xff])))
1521 .unwrap();
1522 let utf8_result = Form::<FormPayload>::from_request(utf8_req, &()).await;
1523 assert!(utf8_result.is_err());
1524
1525 let payload_req = Request::builder()
1527 .method("POST")
1528 .header(
1529 hyper::header::CONTENT_TYPE,
1530 "application/x-www-form-urlencoded",
1531 )
1532 .body(Body::full(Bytes::from("not_valid")))
1533 .unwrap();
1534 let payload_result = Form::<FormPayload>::from_request(payload_req, &()).await;
1535 assert!(payload_result.is_err());
1536 }
1537
1538 #[cfg(feature = "form")]
1539 #[test]
1540 fn test_form_from_request_parts_deserialize_error() {
1541 #[derive(Deserialize, Debug)]
1542 #[allow(dead_code)]
1543 struct FormPayload {
1544 foo: String,
1545 }
1546
1547 let mut parts = Request::builder()
1551 .uri("/search?bar=baz")
1552 .body(())
1553 .unwrap()
1554 .into_parts()
1555 .0;
1556 let result = Form::<FormPayload>::from_request_parts(&mut parts, &());
1557 assert!(result.is_err());
1558 }
1559
1560 #[cfg(feature = "form")]
1561 #[tokio::test]
1562 async fn test_form_get_request_reads_from_query_string() {
1563 #[derive(Deserialize, Debug, PartialEq)]
1564 struct FormPayload {
1565 foo: String,
1566 }
1567
1568 let req = Request::builder()
1569 .method("GET")
1570 .uri("/search?foo=bar")
1571 .body(Body::empty())
1572 .unwrap();
1573 let Form(payload) = Form::<FormPayload>::from_request(req, &()).await.unwrap();
1574 assert_eq!(
1575 payload,
1576 FormPayload {
1577 foo: "bar".to_string(),
1578 }
1579 );
1580 }
1581
1582 #[cfg(feature = "query")]
1583 #[test]
1584 fn test_query_deserialize_error() {
1585 #[derive(Deserialize, Debug)]
1586 #[allow(dead_code)]
1587 struct QueryPayload {
1588 foo: u32,
1589 }
1590
1591 let mut parts = Request::builder()
1592 .uri("/?foo=not_a_number")
1593 .body(())
1594 .unwrap()
1595 .into_parts()
1596 .0;
1597 let result = Query::<QueryPayload>::from_request_parts(&mut parts, &());
1598 assert!(result.is_err());
1599 }
1600
1601 #[test]
1602 fn test_raw_query_present_and_absent() {
1603 let mut with_query = Request::builder()
1604 .uri("/path?a=1&b=2")
1605 .body(())
1606 .unwrap()
1607 .into_parts()
1608 .0;
1609 let RawQuery(q) = RawQuery::from_request_parts(&mut with_query, &()).unwrap();
1610 assert_eq!(q.as_deref(), Some("a=1&b=2"));
1611
1612 let mut without_query = Request::builder()
1613 .uri("/path")
1614 .body(())
1615 .unwrap()
1616 .into_parts()
1617 .0;
1618 let RawQuery(q2) = RawQuery::from_request_parts(&mut without_query, &()).unwrap();
1619 assert!(q2.is_none());
1620 }
1621
1622 #[cfg(feature = "cookies")]
1623 #[test]
1624 fn test_cookies_default() {
1625 let cookies = Cookies::default();
1626 assert!(cookies.get("anything").is_none());
1627 }
1628
1629 #[tokio::test]
1630 async fn test_body_stream_from_request() {
1631 let req = Request::builder()
1632 .body(Body::full(Bytes::from("stream me")))
1633 .unwrap();
1634 let BodyStream(body) = BodyStream::from_request(req, &()).await.unwrap();
1635 let collected = body.collect_bytes(1024).await.unwrap();
1636 assert_eq!(collected.as_ref(), b"stream me");
1637 }
1638
1639 #[cfg(feature = "json")]
1640 #[test]
1641 fn test_is_json_content_type_without_a_slash_is_rejected() {
1642 assert!(!is_json_content_type("not-a-media-type"));
1643 }
1644
1645 fn make_path_parts(params: Vec<(&str, &str)>) -> hyper::http::request::Parts {
1648 let mut parts = Request::builder().body(()).unwrap().into_parts().0;
1649 let path_params = PathParams(
1650 params
1651 .into_iter()
1652 .map(|(k, v)| (std::sync::Arc::from(k), v.to_string()))
1653 .collect(),
1654 );
1655 parts.extensions.insert(path_params);
1656 parts
1657 }
1658
1659 #[test]
1660 fn test_path_tuple_success_and_length_mismatch() {
1661 let mut ok_parts = make_path_parts(vec![("id", "42"), ("name", "hello")]);
1662 let Path((id, name)) =
1663 Path::<(u32, String)>::from_request_parts(&mut ok_parts, &()).unwrap();
1664 assert_eq!(id, 42);
1665 assert_eq!(name, "hello");
1666
1667 let mut too_many = make_path_parts(vec![("a", "1"), ("b", "2"), ("c", "3")]);
1669 assert!(Path::<(u32, String)>::from_request_parts(&mut too_many, &()).is_err());
1670
1671 let mut too_few = make_path_parts(vec![("a", "1")]);
1673 assert!(Path::<(u32, String)>::from_request_parts(&mut too_few, &()).is_err());
1674 }
1675
1676 #[test]
1677 fn test_path_vec_seq_target() {
1678 let mut parts = make_path_parts(vec![("a", "x"), ("b", "y"), ("c", "z")]);
1681 let Path(values) = Path::<Vec<String>>::from_request_parts(&mut parts, &()).unwrap();
1682 assert_eq!(
1683 values,
1684 vec!["x".to_string(), "y".to_string(), "z".to_string()]
1685 );
1686 }
1687
1688 #[test]
1689 fn test_path_scalar_wrong_param_count() {
1690 let mut zero = make_path_parts(vec![]);
1692 assert!(Path::<u32>::from_request_parts(&mut zero, &()).is_err());
1693
1694 let mut two = make_path_parts(vec![("a", "1"), ("b", "2")]);
1696 assert!(Path::<u32>::from_request_parts(&mut two, &()).is_err());
1697
1698 let mut one = make_path_parts(vec![("id", "7")]);
1700 let Path(v) = Path::<u32>::from_request_parts(&mut one, &()).unwrap();
1701 assert_eq!(v, 7);
1702 }
1703
1704 #[test]
1705 fn test_path_option_top_level_target() {
1706 let mut parts = make_path_parts(vec![("id", "9")]);
1712 let Path(v) = Path::<Option<u32>>::from_request_parts(&mut parts, &()).unwrap();
1713 assert_eq!(v, Some(9));
1714 }
1715
1716 #[test]
1717 fn test_path_enum_target() {
1718 let mut parts = make_path_parts(vec![("color", "Red")]);
1719 let Path(c) = Path::<Color>::from_request_parts(&mut parts, &()).unwrap();
1720 assert_eq!(c, Color::Red);
1721 }
1722
1723 #[test]
1724 fn test_path_unit_and_unit_struct_targets() {
1725 #[derive(Deserialize, PartialEq, Debug)]
1726 struct UnitStruct;
1727
1728 let mut parts = make_path_parts(vec![("a", "1"), ("b", "2")]);
1730 let Path(unit_val) = Path::<()>::from_request_parts(&mut parts, &()).unwrap();
1731 assert_eq!(unit_val, ());
1732
1733 let mut empty_parts = make_path_parts(vec![]);
1735 let Path(u) = Path::<UnitStruct>::from_request_parts(&mut empty_parts, &()).unwrap();
1736 assert_eq!(u, UnitStruct);
1737 }
1738
1739 #[test]
1740 fn test_path_newtype_struct_target() {
1741 #[derive(Deserialize, PartialEq, Debug)]
1742 struct Wrapper(u32);
1743
1744 let mut parts = make_path_parts(vec![("id", "77")]);
1745 let Path(Wrapper(v)) = Path::<Wrapper>::from_request_parts(&mut parts, &()).unwrap();
1746 assert_eq!(v, 77);
1747 }
1748
1749 #[test]
1750 fn test_path_ignored_any_top_level_target() {
1751 let mut parts = make_path_parts(vec![("a", "1"), ("b", "2")]);
1756 let result = Path::<serde::de::IgnoredAny>::from_request_parts(&mut parts, &());
1757 assert!(result.is_ok());
1758 }
1759
1760 struct IdentifierVisitor;
1761
1762 impl serde::de::Visitor<'_> for IdentifierVisitor {
1763 type Value = String;
1764
1765 fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1766 formatter.write_str("a string identifier")
1767 }
1768
1769 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
1770 where
1771 E: serde::de::Error,
1772 {
1773 Ok(v.to_string())
1774 }
1775 }
1776
1777 #[test]
1778 fn test_path_deserializer_identifier_direct() {
1779 let params: Vec<(std::sync::Arc<str>, String)> =
1787 vec![(std::sync::Arc::from("k"), "myvalue".to_string())];
1788 let de = PathDeserializer { params: ¶ms };
1789 let result =
1790 serde::de::Deserializer::deserialize_identifier(de, IdentifierVisitor).unwrap();
1791 assert_eq!(result, "myvalue");
1792 }
1793}