salvo_core/serde/
request.rs

1use std::borrow::Cow;
2use std::collections::HashMap;
3
4use indexmap::IndexMap;
5use multimap::MultiMap;
6use serde::de::value::Error as ValError;
7use serde::de::{self, Deserialize, Error as DeError, IntoDeserializer};
8use serde::forward_to_deserialize_any;
9use serde_json::value::RawValue;
10
11use crate::Request;
12use crate::extract::Metadata;
13use crate::extract::metadata::{Field, Source, SourceFrom, SourceParser};
14use crate::http::ParseError;
15use crate::http::form::FormData;
16use crate::http::header::HeaderMap;
17
18use super::{CowValue, FlatValue, VecValue};
19
20pub async fn from_request<'de, T>(
21    req: &'de mut Request,
22    metadata: &'de Metadata,
23) -> Result<T, ParseError>
24where
25    T: Deserialize<'de>,
26{
27    // Ensure body is parsed correctly.
28    if let Some(ctype) = req.content_type() {
29        match ctype.subtype() {
30            mime::WWW_FORM_URLENCODED | mime::FORM_DATA => {
31                if metadata.has_body_required() {
32                    let _ = req.form_data().await;
33                }
34            }
35            mime::JSON => {
36                if metadata.has_body_required() {
37                    let _ = req.payload().await;
38                }
39            }
40            _ => {}
41        }
42    }
43    Ok(T::deserialize(RequestDeserializer::new(req, metadata)?)?)
44}
45
46#[derive(Clone, Debug)]
47pub(crate) enum Payload<'a> {
48    FormData(&'a FormData),
49    JsonStr(&'a str),
50    JsonMap(HashMap<&'a str, &'a RawValue>),
51}
52impl Payload<'_> {
53    #[allow(dead_code)]
54    pub(crate) fn is_form_data(&self) -> bool {
55        matches!(*self, Self::FormData(_))
56    }
57    pub(crate) fn is_json_str(&self) -> bool {
58        matches!(*self, Self::JsonStr(_))
59    }
60    pub(crate) fn is_json_map(&self) -> bool {
61        matches!(*self, Self::JsonMap(_))
62    }
63}
64
65#[derive(Debug)]
66pub(crate) struct RequestDeserializer<'de> {
67    params: &'de IndexMap<String, String>,
68    queries: &'de MultiMap<String, String>,
69    #[cfg(feature = "cookie")]
70    cookies: &'de cookie::CookieJar,
71    headers: &'de HeaderMap,
72    payload: Option<Payload<'de>>,
73    metadata: &'de Metadata,
74    field_index: isize,
75    field_flatten: bool,
76    field_source: Option<Source>,
77    field_str_value: Option<&'de str>,
78    field_vec_value: Option<Vec<CowValue<'de>>>,
79}
80
81impl<'de> RequestDeserializer<'de> {
82    /// Construct a new `RequestDeserializer<I, E>`.
83    pub(crate) fn new(request: &'de Request, metadata: &'de Metadata) -> Result<Self, ParseError> {
84        let mut payload = None;
85
86        if metadata.has_body_required() {
87            if let Some(ctype) = request.content_type() {
88                match ctype.subtype() {
89                    mime::WWW_FORM_URLENCODED | mime::FORM_DATA => {
90                        payload = request.form_data.get().map(Payload::FormData);
91                    }
92                    mime::JSON => {
93                        if let Some(data) = request.payload.get() {
94                            if !data.is_empty() {
95                                // https://github.com/serde-rs/json/issues/903
96                                payload = match serde_json::from_slice::<HashMap<&str, &RawValue>>(
97                                    data,
98                                ) {
99                                    Ok(map) => Some(Payload::JsonMap(map)),
100                                    Err(e) => {
101                                        tracing::warn!(error = ?e, "`RequestDeserializer` serde parse json payload failed");
102                                        Some(Payload::JsonStr(std::str::from_utf8(data)?))
103                                    }
104                                };
105                            }
106                        }
107                    }
108                    _ => {}
109                }
110            }
111        }
112        Ok(RequestDeserializer {
113            params: request.params(),
114            queries: request.queries(),
115            headers: request.headers(),
116            #[cfg(feature = "cookie")]
117            cookies: request.cookies(),
118            payload,
119            metadata,
120            field_index: -1,
121            field_flatten: false,
122            field_source: None,
123            field_str_value: None,
124            field_vec_value: None,
125        })
126    }
127
128    fn real_parser(&self, source: Source) -> SourceParser {
129        let mut parser = source.parser;
130        if parser == SourceParser::Smart {
131            if source.from == SourceFrom::Body {
132                if let Some(payload) = &self.payload {
133                    if payload.is_json_map() || payload.is_json_str() {
134                        parser = SourceParser::Json;
135                    } else {
136                        parser = SourceParser::MultiMap;
137                    }
138                } else {
139                    parser = SourceParser::MultiMap;
140                }
141            } else if source.from == SourceFrom::Query || source.from == SourceFrom::Header {
142                parser = SourceParser::Flat;
143            } else {
144                parser = SourceParser::MultiMap;
145            }
146        }
147        parser
148    }
149
150    fn deserialize_value<T>(&mut self, seed: T) -> Result<T::Value, ValError>
151    where
152        T: de::DeserializeSeed<'de>,
153    {
154        if self.field_flatten {
155            let field = self
156                .metadata
157                .fields
158                .get(self.field_index as usize)
159                .expect("field must exist.");
160            let metadata = field.metadata.expect("field's metadata must exist");
161            seed.deserialize(RequestDeserializer {
162                params: self.params,
163                queries: self.queries,
164                headers: self.headers,
165                #[cfg(feature = "cookie")]
166                cookies: self.cookies,
167                payload: self.payload.clone(),
168                metadata,
169                field_index: -1,
170                field_flatten: false,
171                field_source: None,
172                field_str_value: None,
173                field_vec_value: None,
174            })
175        } else {
176            let source = self
177                .field_source
178                .take()
179                .expect("`MapAccess::next_value` called before next_key");
180
181            let parser = self.real_parser(source);
182            if source.from == SourceFrom::Body && parser == SourceParser::Json {
183                // panic because this indicates a bug in the program rather than an expected failure.
184                let value = self
185                    .field_str_value
186                    .expect("MapAccess::next_value called before next_key");
187                let mut value = serde_json::Deserializer::new(serde_json::de::StrRead::new(value));
188
189                seed.deserialize(&mut value)
190                    .map_err(|_| ValError::custom("parse value error"))
191            } else if let Some(value) = self.field_str_value.take() {
192                seed.deserialize(CowValue(value.into()))
193            } else if let Some(value) = self.field_vec_value.take() {
194                if source.from == SourceFrom::Query || source.from == SourceFrom::Header {
195                    seed.deserialize(FlatValue(value))
196                } else {
197                    seed.deserialize(VecValue(value.into_iter()))
198                }
199            } else {
200                Err(ValError::custom("parse value error"))
201            }
202        }
203    }
204
205    #[allow(unreachable_patterns)]
206    fn fill_value(&mut self, field: &'de Field) -> bool {
207        if field.flatten {
208            self.field_flatten = true;
209            return true;
210        }
211        let sources = if !field.sources.is_empty() {
212            &field.sources
213        } else if !self.metadata.default_sources.is_empty() {
214            &self.metadata.default_sources
215        } else {
216            tracing::error!("no sources for field {}", field.decl_name);
217            return false;
218        };
219
220        let field_name = if let Some(rename) = field.rename {
221            rename
222        } else if let Some(serde_rename) = field.serde_rename {
223            serde_rename
224        } else if let Some(rename_all) = self.metadata.rename_all {
225            &*rename_all.apply_to_field(field.decl_name)
226        } else if let Some(serde_rename_all) = self.metadata.serde_rename_all {
227            &*serde_rename_all.apply_to_field(field.decl_name)
228        } else {
229            field.decl_name
230        };
231
232        for source in sources.iter().cloned() {
233            match source.from {
234                SourceFrom::Param => {
235                    let mut value = self.params.get(field_name);
236                    if value.is_none() {
237                        for alias in &field.aliases {
238                            value = self.params.get(*alias);
239                            if value.is_some() {
240                                break;
241                            }
242                        }
243                    }
244                    if let Some(value) = value {
245                        self.field_str_value = Some(value);
246                        self.field_source = Some(source);
247                        return true;
248                    }
249                }
250                SourceFrom::Query => {
251                    let mut value = self.queries.get_vec(field_name);
252                    if value.is_none() {
253                        for alias in &field.aliases {
254                            value = self.queries.get_vec(*alias);
255                            if value.is_some() {
256                                break;
257                            }
258                        }
259                    }
260                    if let Some(value) = value {
261                        self.field_vec_value =
262                            Some(value.iter().map(|v| CowValue(v.into())).collect());
263                        self.field_source = Some(source);
264                        return true;
265                    }
266                }
267                SourceFrom::Header => {
268                    let mut value = None;
269                    if self.headers.contains_key(field_name) {
270                        value = Some(self.headers.get_all(field_name))
271                    } else {
272                        for alias in &field.aliases {
273                            if self.headers.contains_key(*alias) {
274                                value = Some(self.headers.get_all(*alias));
275                                break;
276                            }
277                        }
278                    };
279                    if let Some(value) = value {
280                        self.field_vec_value = Some(
281                            value
282                                .iter()
283                                .map(|v| CowValue(Cow::from(v.to_str().unwrap_or_default())))
284                                .collect(),
285                        );
286                        self.field_source = Some(source);
287                        return true;
288                    }
289                }
290                #[cfg(feature = "cookie")]
291                SourceFrom::Cookie => {
292                    let mut value = None;
293                    if let Some(cookie) = self.cookies.get(field_name.as_ref()) {
294                        value = Some(cookie.value());
295                    } else {
296                        for alias in &field.aliases {
297                            if let Some(cookie) = self.cookies.get(alias) {
298                                value = Some(cookie.value());
299                                break;
300                            }
301                        }
302                    };
303                    if let Some(value) = value {
304                        self.field_str_value = Some(value);
305                        self.field_source = Some(source);
306                        return true;
307                    }
308                }
309                SourceFrom::Body => {
310                    let parser = self.real_parser(source);
311                    match parser {
312                        SourceParser::Json => {
313                            if let Some(payload) = &self.payload {
314                                match payload {
315                                    Payload::FormData(form_data) => {
316                                        let mut value = form_data.fields.get(field_name);
317                                        if value.is_none() {
318                                            for alias in &field.aliases {
319                                                value = form_data.fields.get(*alias);
320                                                if value.is_some() {
321                                                    break;
322                                                }
323                                            }
324                                        }
325                                        if let Some(value) = value {
326                                            self.field_str_value = Some(value);
327                                            self.field_source = Some(source);
328                                            return true;
329                                        }
330                                        return false;
331                                    }
332                                    Payload::JsonMap(map) => {
333                                        let mut value = map.get(field_name);
334                                        if value.is_none() {
335                                            for alias in &field.aliases {
336                                                value = map.get(alias);
337                                                if value.is_some() {
338                                                    break;
339                                                }
340                                            }
341                                        }
342                                        if let Some(value) = value {
343                                            self.field_str_value = Some(value.get());
344                                            self.field_source = Some(source);
345                                            return true;
346                                        }
347                                        return false;
348                                    }
349                                    Payload::JsonStr(value) => {
350                                        self.field_str_value = Some(*value);
351                                        self.field_source = Some(source);
352                                        return true;
353                                    }
354                                }
355                            } else {
356                                return false;
357                            }
358                        }
359                        SourceParser::MultiMap => {
360                            if let Some(Payload::FormData(form_data)) = self.payload {
361                                let mut value = form_data.fields.get_vec(field_name);
362                                if value.is_none() {
363                                    for alias in &field.aliases {
364                                        value = form_data.fields.get_vec(*alias);
365                                        if value.is_some() {
366                                            break;
367                                        }
368                                    }
369                                }
370                                if let Some(value) = value {
371                                    self.field_vec_value = Some(
372                                        value.iter().map(|v| CowValue(Cow::from(v))).collect(),
373                                    );
374                                    self.field_source = Some(source);
375                                    return true;
376                                }
377                            }
378                            return false;
379                        }
380                        _ => {
381                            panic!("unsupported source parser: {parser:?}");
382                        }
383                    }
384                }
385            }
386        }
387        false
388    }
389    fn next(&mut self) -> Option<Cow<'_, str>> {
390        while self.field_index < self.metadata.fields.len() as isize - 1 {
391            self.field_index += 1;
392            let field = &self.metadata.fields[self.field_index as usize];
393            self.field_flatten = field.flatten;
394            self.field_str_value = None;
395            self.field_vec_value = None;
396
397            if self.fill_value(field) {
398                return field.serde_rename.map(Cow::from).or_else(|| {
399                    if let Some(serde_rename_all) = self.metadata.serde_rename_all {
400                        Some(Cow::Owned(serde_rename_all.apply_to_field(field.decl_name)))
401                    } else {
402                        Some(Cow::from(field.decl_name))
403                    }
404                });
405            }
406        }
407        None
408    }
409}
410
411impl<'de> de::Deserializer<'de> for RequestDeserializer<'de> {
412    type Error = ValError;
413
414    #[inline]
415    fn deserialize_any<V>(mut self, visitor: V) -> Result<V::Value, Self::Error>
416    where
417        V: de::Visitor<'de>,
418    {
419        visitor.visit_map(&mut self)
420    }
421
422    #[inline]
423    fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>
424    where
425        V: de::Visitor<'de>,
426    {
427        self.deserialize_seq(visitor)
428    }
429
430    forward_to_deserialize_any! {
431        bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
432        bytes byte_buf option unit unit_struct newtype_struct tuple_struct map seq
433        struct enum identifier ignored_any
434    }
435}
436
437impl<'de> de::MapAccess<'de> for RequestDeserializer<'de> {
438    type Error = ValError;
439
440    #[inline]
441    fn next_key_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
442    where
443        T: de::DeserializeSeed<'de>,
444    {
445        match self.next() {
446            Some(key) => seed.deserialize(key.into_deserializer()).map(Some),
447            None => Ok(None),
448        }
449    }
450
451    #[inline]
452    fn next_value_seed<T>(&mut self, seed: T) -> Result<T::Value, Self::Error>
453    where
454        T: de::DeserializeSeed<'de>,
455    {
456        self.deserialize_value(seed)
457    }
458
459    #[inline]
460    fn next_entry_seed<TK, TV>(
461        &mut self,
462        kseed: TK,
463        vseed: TV,
464    ) -> Result<Option<(TK::Value, TV::Value)>, Self::Error>
465    where
466        TK: de::DeserializeSeed<'de>,
467        TV: de::DeserializeSeed<'de>,
468    {
469        match self.next() {
470            Some(key) => {
471                let key = kseed.deserialize(key.into_deserializer())?;
472                let value = self.deserialize_value(vseed)?;
473                Ok(Some((key, value)))
474            }
475            None => Ok(None),
476        }
477    }
478}
479
480#[cfg(test)]
481mod tests {
482    use serde::{Deserialize, Serialize};
483
484    use crate::macros::Extractible;
485    use crate::test::TestClient;
486
487    #[tokio::test]
488    async fn test_de_request_from_query() {
489        #[derive(Deserialize, Extractible, Eq, PartialEq, Debug)]
490        #[salvo(extract(default_source(from = "query")))]
491        struct RequestData {
492            q1: String,
493            q2: i64,
494        }
495        let mut req = TestClient::get("http://127.0.0.1:8698/test/1234/param2v")
496            .query("q1", "q1v")
497            .query("q2", "23")
498            .build();
499        let data: RequestData = req.extract().await.unwrap();
500        assert_eq!(
501            data,
502            RequestData {
503                q1: "q1v".to_owned(),
504                q2: 23
505            }
506        );
507    }
508
509    #[tokio::test]
510    async fn test_de_request_with_lifetime() {
511        #[derive(Deserialize, Extractible, Eq, PartialEq, Debug)]
512        #[salvo(extract(default_source(from = "query")))]
513        struct RequestData<'a> {
514            #[salvo(extract(source(from = "param"), source(from = "query")))]
515            #[salvo(extract(source(from = "body")))]
516            q1: &'a str,
517            // #[salvo(extract(source(from = "query")))]
518            // #[serde(alias = "param2", alias = "param3")]
519            // q2: i64,
520        }
521
522        let mut req = TestClient::get("http://127.0.0.1:8698/test/1234/param2v")
523            .query("q1", "q1v")
524            .query("q2", "23")
525            .build();
526        let data: RequestData<'_> = req.extract().await.unwrap();
527        assert_eq!(data, RequestData { q1: "q1v" });
528    }
529
530    #[tokio::test]
531    async fn test_de_request_with_rename() {
532        #[derive(Deserialize, Extractible, Eq, PartialEq, Debug)]
533        #[salvo(extract(default_source(from = "query")))]
534        struct RequestData<'a> {
535            #[salvo(extract(source(from = "param"), source(from = "query"), rename = "abc"))]
536            q1: &'a str,
537        }
538
539        let mut req = TestClient::get("http://127.0.0.1:8698/test/1234/param2v")
540            .query("abc", "q1v")
541            .build();
542        let data: RequestData<'_> = req.extract().await.unwrap();
543        assert_eq!(data, RequestData { q1: "q1v" });
544    }
545
546    #[tokio::test]
547    async fn test_de_request_with_rename_all() {
548        #[derive(Deserialize, Extractible, Eq, PartialEq, Debug)]
549        #[salvo(extract(default_source(from = "query"), rename_all = "PascalCase"))]
550        struct RequestData<'a> {
551            first_name: &'a str,
552            #[salvo(extract(rename = "lastName"))]
553            last_name: &'a str,
554        }
555
556        let mut req = TestClient::get("http://127.0.0.1:8698/test/1234/param2v")
557            .query("FirstName", "chris")
558            .query("lastName", "young")
559            .build();
560        let data: RequestData<'_> = req.extract().await.unwrap();
561        assert_eq!(
562            data,
563            RequestData {
564                first_name: "chris",
565                last_name: "young"
566            }
567        );
568    }
569
570    #[tokio::test]
571    async fn test_de_request_with_multi_sources() {
572        #[derive(Deserialize, Extractible, Eq, PartialEq, Debug)]
573        #[salvo(extract(default_source(from = "query")))]
574        struct RequestData<'a> {
575            #[salvo(extract(source(from = "param")))]
576            #[salvo(extract(alias = "param1"))]
577            p1: String,
578            #[salvo(extract(source(from = "param"), alias = "param2"))]
579            p2: &'a str,
580            #[salvo(extract(source(from = "param"), alias = "param3"))]
581            p3: usize,
582            // #[salvo(extract(source(from = "query")))]
583            q1: String,
584            // #[salvo(extract(source(from = "query")))]
585            q2: i64,
586            // #[salvo(extract(source(from = "body", parse = "json")))]
587            // body: RequestBody<'a>,
588        }
589
590        let mut req = TestClient::get("http://127.0.0.1:8698/test/1234/param2v")
591            .query("q1", "q1v")
592            .query("q2", "23")
593            .build();
594        req.params.insert("param1", "param1v".into());
595        req.params.insert("p2", "921".into());
596        req.params.insert("p3", "89785".into());
597        let data: RequestData = req.extract().await.unwrap();
598        assert_eq!(
599            data,
600            RequestData {
601                p1: "param1v".into(),
602                p2: "921",
603                p3: 89785,
604                q1: "q1v".into(),
605                q2: 23
606            }
607        );
608    }
609
610    #[tokio::test]
611    async fn test_de_request_with_json_vec() {
612        #[derive(Deserialize, Extractible, Eq, PartialEq, Debug)]
613        #[salvo(extract(default_source(from = "body", parse = "json")))]
614        struct RequestData<'a> {
615            #[salvo(extract(source(from = "param")))]
616            p2: &'a str,
617            users: Vec<User>,
618        }
619        #[derive(Deserialize, Serialize, Eq, PartialEq, Debug)]
620        struct User {
621            id: i64,
622            name: String,
623        }
624
625        let mut req = TestClient::get("http://127.0.0.1:8698/test/1234/param2v")
626            .json(&vec![
627                User {
628                    id: 1,
629                    name: "chris".into(),
630                },
631                User {
632                    id: 2,
633                    name: "young".into(),
634                },
635            ])
636            .build();
637        req.params.insert("p2", "921".into());
638        let data: RequestData = req.extract().await.unwrap();
639        assert_eq!(
640            data,
641            RequestData {
642                p2: "921",
643                users: vec![
644                    User {
645                        id: 1,
646                        name: "chris".into()
647                    },
648                    User {
649                        id: 2,
650                        name: "young".into()
651                    }
652                ]
653            }
654        );
655    }
656
657    #[tokio::test]
658    async fn test_de_request_with_json_bool() {
659        #[derive(Deserialize, Extractible, Eq, PartialEq, Debug)]
660        #[salvo(extract(default_source(from = "body", parse = "json")))]
661        struct RequestData<'a> {
662            #[salvo(extract(source(from = "param")))]
663            p2: &'a str,
664            b: bool,
665        }
666
667        let mut req = TestClient::get("http://127.0.0.1:8698/test/1234/param2v")
668            .json(&true)
669            .build();
670        req.params.insert("p2", "921".into());
671        let data: RequestData = req.extract().await.unwrap();
672        assert_eq!(data, RequestData { p2: "921", b: true });
673    }
674
675    #[tokio::test]
676    async fn test_de_request_with_json_str() {
677        #[derive(Deserialize, Extractible, Eq, PartialEq, Debug)]
678        #[salvo(extract(default_source(from = "body", parse = "json")))]
679        struct RequestData<'a> {
680            #[salvo(extract(source(from = "param")))]
681            p2: &'a str,
682            s: &'a str,
683        }
684
685        let mut req = TestClient::get("http://127.0.0.1:8698/test/1234/param2v")
686            .json(&"abcd-good")
687            .build();
688        req.params.insert("p2", "921".into());
689        let data: RequestData = req.extract().await.unwrap();
690        assert_eq!(
691            data,
692            RequestData {
693                p2: "921",
694                s: "abcd-good"
695            }
696        );
697    }
698
699    #[tokio::test]
700    async fn test_de_request_with_form_json_str() {
701        #[derive(Deserialize, Eq, PartialEq, Debug)]
702        struct User<'a> {
703            name: &'a str,
704            age: usize,
705        }
706        #[derive(Deserialize, Extractible, Eq, PartialEq, Debug)]
707        #[salvo(extract(default_source(from = "body", parse = "json")))]
708        struct RequestData<'a> {
709            #[salvo(extract(source(from = "param")))]
710            p2: &'a str,
711            user: User<'a>,
712        }
713        let mut req = TestClient::get("http://127.0.0.1:8698/test/1234/param2v")
714            .raw_form(r#"user={"name": "chris", "age": 20}"#)
715            .build();
716        req.params.insert("p2", "921".into());
717        let data: RequestData = req.extract().await.unwrap();
718        assert_eq!(
719            data,
720            RequestData {
721                p2: "921",
722                user: User {
723                    name: "chris",
724                    age: 20
725                }
726            }
727        );
728    }
729
730    #[tokio::test]
731    async fn test_de_request_with_extract_rename_all() {
732        #[derive(Deserialize, Extractible, Eq, PartialEq, Debug)]
733        #[salvo(extract(rename_all = "kebab-case", default_source(from = "query")))]
734        struct RequestData {
735            full_name: String,
736            #[salvo(extract(rename = "currAge"))]
737            curr_age: usize,
738        }
739        let mut req = TestClient::get(
740            "http://127.0.0.1:8698/test/1234/param2v?full-name=chris+young&currAge=20",
741        )
742        .build();
743        let data: RequestData = req.extract().await.unwrap();
744        assert_eq!(
745            data,
746            RequestData {
747                full_name: "chris young".into(),
748                curr_age: 20
749            }
750        );
751    }
752
753    #[tokio::test]
754    async fn test_de_request_with_serde_rename_all() {
755        #[derive(Deserialize, Extractible, Eq, PartialEq, Debug)]
756        #[salvo(extract(default_source(from = "query")))]
757        #[serde(rename_all = "kebab-case")]
758        struct RequestData {
759            full_name: String,
760            #[salvo(extract(rename = "currAge"))]
761            curr_age: usize,
762        }
763        let mut req = TestClient::get(
764            "http://127.0.0.1:8698/test/1234/param2v?full-name=chris+young&currAge=20",
765        )
766        .build();
767        let data: RequestData = req.extract().await.unwrap();
768        assert_eq!(
769            data,
770            RequestData {
771                full_name: "chris young".into(),
772                curr_age: 20
773            }
774        );
775    }
776
777    #[tokio::test]
778    async fn test_de_request_with_both_rename_all() {
779        #[derive(Deserialize, Extractible, Eq, PartialEq, Debug)]
780        #[salvo(extract(rename_all = "kebab-case", default_source(from = "query")))]
781        #[serde(rename_all = "camelCase")]
782        struct RequestData {
783            full_name: String,
784            #[salvo(extract(rename = "currAge"))]
785            curr_age: usize,
786        }
787        let mut req = TestClient::get(
788            "http://127.0.0.1:8698/test/1234/param2v?full-name=chris+young&currAge=20",
789        )
790        .build();
791        let data: RequestData = req.extract().await.unwrap();
792        assert_eq!(
793            data,
794            RequestData {
795                full_name: "chris young".into(),
796                curr_age: 20
797            }
798        );
799    }
800
801    #[tokio::test]
802    async fn test_de_request_url_array() {
803        #[derive(Deserialize, Extractible, Eq, PartialEq, Debug)]
804        #[salvo(extract(default_source(from = "query")))]
805        struct RequestData {
806            ids: Vec<String>,
807        }
808        let mut req =
809            TestClient::get("http://127.0.0.1:8698/test/1234/param2v?ids=[3,2,11]").build();
810        let data: RequestData = req.extract().await.unwrap();
811        assert_eq!(
812            data,
813            RequestData {
814                ids: vec!["3".to_owned(), "2".to_owned(), "11".to_owned()]
815            }
816        );
817        let mut req = TestClient::get(
818            r#"http://127.0.0.1:8698/test/1234/param2v?ids=['3',  '2',"11","1,2"]"#,
819        )
820        .build();
821        let data: RequestData = req.extract().await.unwrap();
822        assert_eq!(
823            data,
824            RequestData {
825                ids: vec![
826                    "3".to_owned(),
827                    "2".to_owned(),
828                    "11".to_owned(),
829                    "1,2".to_owned()
830                ]
831            }
832        );
833    }
834
835    #[tokio::test]
836    async fn test_de_request_url_array2() {
837        #[derive(Deserialize, Extractible, Eq, PartialEq, Debug)]
838        #[salvo(extract(default_source(from = "query")))]
839        struct RequestData {
840            ids: Vec<i64>,
841        }
842        let mut req =
843            TestClient::get("http://127.0.0.1:8698/test/1234/param2v?ids=[3,2,11]").build();
844        let data: RequestData = req.extract().await.unwrap();
845        assert_eq!(
846            data,
847            RequestData {
848                ids: vec![3, 2, 11]
849            }
850        );
851    }
852}