pavex/request/query/
query_params.rs1use pavex_macros::methods;
2
3use crate::request::RequestHead;
4
5use super::errors::{ExtractQueryParamsError, QueryDeserializationError};
6
7#[doc(alias = "Query")]
35#[doc(alias = "QueryParameters")]
36pub struct QueryParams<T>(
37 pub T,
39);
40
41#[methods]
42impl<T> QueryParams<T> {
43 #[request_scoped(pavex = crate, id = "QUERY_PARAMS_EXTRACT")]
49 pub fn extract<'request>(
50 request_head: &'request RequestHead,
51 ) -> Result<Self, ExtractQueryParamsError>
52 where
53 T: serde::Deserialize<'request>,
54 {
55 let query = request_head.target.query().unwrap_or_default();
56 parse(query).map(QueryParams)
57 }
58}
59
60fn parse<'a, T>(s: &'a str) -> Result<T, ExtractQueryParamsError>
62where
63 T: serde::Deserialize<'a>,
64{
65 let deserializer = serde_html_form::Deserializer::new(form_urlencoded::parse(s.as_bytes()));
66 serde_path_to_error::deserialize(deserializer)
67 .map_err(QueryDeserializationError::new)
68 .map_err(ExtractQueryParamsError::QueryDeserializationError)
69}
70
71#[cfg(test)]
72mod tests {
73 use std::borrow::Cow;
74
75 use super::*;
76
77 #[test]
78 fn test_parse() {
79 #[derive(serde::Deserialize, Debug, PartialEq)]
80 struct Home<'a> {
81 home_id: u32,
82 home_price: f64,
83 home_name: Cow<'a, str>,
84 }
85
86 let query = "home_id=1&home_price=0.1&home_name=Hi%20there";
87 let expected = Home {
88 home_id: 1,
89 home_price: 0.1,
90 home_name: Cow::Borrowed("Hi there"),
91 };
92 let actual: Home = parse(query).unwrap();
93 assert_eq!(expected, actual);
94 }
95
96 #[test]
97 fn test_sequence() {
98 #[derive(serde::Deserialize, Debug, PartialEq)]
99 struct Home {
100 room_ids: Vec<u32>,
101 }
102
103 let query = "room_ids=1&room_ids=2";
104 let expected = Home {
105 room_ids: vec![1, 2],
106 };
107 let actual: Home = parse(query).unwrap();
108 assert_eq!(expected, actual);
109 }
110
111 #[test]
112 fn test_sequence_with_brackets() {
113 #[derive(serde::Deserialize, Debug, PartialEq)]
114 struct Home {
115 #[serde(rename = "room_ids[]")]
116 room_ids: Vec<u32>,
117 }
118
119 let query = "room_ids[]=1&room_ids[]=2";
120 let expected = Home {
121 room_ids: vec![1, 2],
122 };
123 let actual: Home = parse(query).unwrap();
124 assert_eq!(expected, actual);
125 }
126}