1use serde::de::{self, DeserializeOwned, IntoDeserializer, Visitor};
6use serde::de::value::Error;
7
8use super::{rejection, FromRequestParts, RequestParts};
9use crate::response::{Response, STATUS_CODE_REASON_PHRASE};
10use crate::url::URL;
11
12#[derive(Debug, Clone, PartialEq, Eq)]
19pub struct Query<T>(pub T);
20
21impl<T> std::ops::Deref for Query<T> {
22 type Target = T;
23 fn deref(&self) -> &T {
24 &self.0
25 }
26}
27
28impl<S, T: DeserializeOwned> FromRequestParts<S> for Query<T> {
29 fn from_request_parts(parts: &RequestParts<'_, S>) -> Result<Self, Response> {
30 let uri = &parts.request.request_uri;
31 let query = uri.split_once('?').map(|(_, q)| q).unwrap_or("");
32 let query = query.split('#').next().unwrap_or("");
33 from_urlencoded(query)
34 .map(Query)
35 .map_err(|e| rejection(parts.request, STATUS_CODE_REASON_PHRASE.n400_bad_request, &format!("query string: {e}")))
36 }
37}
38
39#[derive(Debug, Clone, PartialEq, Eq)]
46pub struct Form<T>(pub T);
47
48impl<T> std::ops::Deref for Form<T> {
49 type Target = T;
50 fn deref(&self) -> &T {
51 &self.0
52 }
53}
54
55const FORM_TYPE: &str = "application/x-www-form-urlencoded";
56
57impl<S, T: DeserializeOwned> FromRequestParts<S> for Form<T> {
58 fn from_request_parts(parts: &RequestParts<'_, S>) -> Result<Self, Response> {
59 let request = parts.request;
60 let content_type: &str = request.header("Content-Type").map(|h| h.value.as_ref()).unwrap_or("");
61 let essence = content_type.split(';').next().unwrap_or("").trim();
62 if !essence.eq_ignore_ascii_case(FORM_TYPE) {
63 let detail = format!("expected Content-Type {FORM_TYPE}");
64 return Err(rejection(request, STATUS_CODE_REASON_PHRASE.n415_unsupported_media_type, &detail));
65 }
66 let body = std::str::from_utf8(&request.body)
67 .map_err(|_| rejection(request, STATUS_CODE_REASON_PHRASE.n400_bad_request, "request body is not valid UTF-8"))?;
68 from_urlencoded(body)
69 .map(Form)
70 .map_err(|e| rejection(request, STATUS_CODE_REASON_PHRASE.n422_unprocessable_entity, &format!("form: {e}")))
71 }
72}
73
74pub(crate) fn from_urlencoded<T: DeserializeOwned>(input: &str) -> Result<T, Error> {
76 let mut pairs: Vec<(String, Vec<String>)> = Vec::new();
79 let mut index: std::collections::HashMap<String, usize> = std::collections::HashMap::new();
80 for pair in input.split('&').filter(|p| !p.is_empty()) {
81 let (k, v) = pair.split_once('=').unwrap_or((pair, ""));
82 let (k, v) = (URL::form_decode(k), URL::form_decode(v));
83 match index.get(&k) {
84 Some(&i) => pairs[i].1.push(v),
85 None => {
86 index.insert(k.clone(), pairs.len());
87 pairs.push((k, vec![v]));
88 }
89 }
90 }
91 T::deserialize(Pairs(pairs))
92}
93
94#[doc(hidden)]
97pub fn fuzz(input: &str) {
98 use std::collections::HashMap;
99 let _ = from_urlencoded::<HashMap<String, String>>(input);
100 let _ = from_urlencoded::<HashMap<String, Vec<String>>>(input);
101 let _ = from_urlencoded::<HashMap<String, Option<u64>>>(input);
102 let _ = from_urlencoded::<HashMap<String, (bool, char)>>(input);
103 let _ = from_urlencoded::<Vec<(String, f64)>>(input);
104}
105
106struct Pairs(Vec<(String, Vec<String>)>);
107
108impl<'de> de::Deserializer<'de> for Pairs {
109 type Error = Error;
110
111 fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
112 visitor.visit_map(PairsAccess { pairs: self.0.into_iter(), value: None })
113 }
114
115 serde::forward_to_deserialize_any! {
116 bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
117 bytes byte_buf option unit unit_struct newtype_struct seq tuple
118 tuple_struct map struct enum identifier ignored_any
119 }
120}
121
122struct PairsAccess {
123 pairs: std::vec::IntoIter<(String, Vec<String>)>,
124 value: Option<Vec<String>>,
125}
126
127impl<'de> de::MapAccess<'de> for PairsAccess {
128 type Error = Error;
129
130 fn next_key_seed<K: de::DeserializeSeed<'de>>(&mut self, seed: K) -> Result<Option<K::Value>, Error> {
131 match self.pairs.next() {
132 Some((key, values)) => {
133 self.value = Some(values);
134 seed.deserialize(key.into_deserializer()).map(Some)
135 }
136 None => Ok(None),
137 }
138 }
139
140 fn next_value_seed<V: de::DeserializeSeed<'de>>(&mut self, seed: V) -> Result<V::Value, Error> {
141 let values = self.value.take().unwrap_or_default();
142 seed.deserialize(Values(values))
143 }
144}
145
146struct Values(Vec<String>);
149
150impl Values {
151 fn last(self) -> String {
152 self.0.into_iter().next_back().unwrap_or_default()
153 }
154
155 fn parse<T: std::str::FromStr>(self, what: &str) -> Result<T, Error>
156 where
157 T::Err: std::fmt::Display,
158 {
159 let value = self.last();
160 value.parse::<T>().map_err(|e| de::Error::custom(format!("{value:?} is not a valid {what}: {e}")))
161 }
162}
163
164macro_rules! parse_scalar {
165 ($($method:ident => $visit:ident $t:ty),*) => {$(
166 fn $method<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
167 visitor.$visit(self.parse::<$t>(stringify!($t))?)
168 }
169 )*};
170}
171
172impl<'de> de::Deserializer<'de> for Values {
173 type Error = Error;
174
175 fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
176 if self.0.len() > 1 {
177 return self.deserialize_seq(visitor);
178 }
179 visitor.visit_string(self.last())
180 }
181
182 parse_scalar! {
183 deserialize_bool => visit_bool bool,
184 deserialize_i8 => visit_i8 i8, deserialize_i16 => visit_i16 i16,
185 deserialize_i32 => visit_i32 i32, deserialize_i64 => visit_i64 i64,
186 deserialize_i128 => visit_i128 i128,
187 deserialize_u8 => visit_u8 u8, deserialize_u16 => visit_u16 u16,
188 deserialize_u32 => visit_u32 u32, deserialize_u64 => visit_u64 u64,
189 deserialize_u128 => visit_u128 u128,
190 deserialize_f32 => visit_f32 f32, deserialize_f64 => visit_f64 f64,
191 deserialize_char => visit_char char
192 }
193
194 fn deserialize_str<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
195 visitor.visit_string(self.last())
196 }
197
198 fn deserialize_string<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
199 visitor.visit_string(self.last())
200 }
201
202 fn deserialize_option<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
203 if self.0.iter().all(|v| v.is_empty()) {
204 visitor.visit_none()
205 } else {
206 visitor.visit_some(self)
207 }
208 }
209
210 fn deserialize_newtype_struct<V: Visitor<'de>>(self, _name: &'static str, visitor: V) -> Result<V::Value, Error> {
211 visitor.visit_newtype_struct(self)
212 }
213
214 fn deserialize_seq<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
215 visitor.visit_seq(de::value::SeqDeserializer::new(self.0.into_iter().map(|v| Values(vec![v]))))
216 }
217
218 fn deserialize_enum<V: Visitor<'de>>(
219 self,
220 _name: &'static str,
221 _variants: &'static [&'static str],
222 visitor: V,
223 ) -> Result<V::Value, Error> {
224 visitor.visit_enum(self.last().into_deserializer())
225 }
226
227 fn deserialize_unit<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
228 visitor.visit_unit()
229 }
230
231 serde::forward_to_deserialize_any! {
232 bytes byte_buf unit_struct tuple tuple_struct map struct identifier ignored_any
233 }
234}
235
236impl<'de> IntoDeserializer<'de, Error> for Values {
237 type Deserializer = Values;
238 fn into_deserializer(self) -> Values {
239 self
240 }
241}