poem_openapi/param/
query.rs

1use std::ops::{Deref, DerefMut};
2
3use poem::{Request, RequestBody, Result};
4
5use crate::{
6    base::UrlQuery,
7    error::ParseParamError,
8    registry::{MetaParamIn, MetaSchemaRef, Registry},
9    types::ParseFromParameter,
10    ApiExtractor, ApiExtractorType, ExtractParamOptions,
11};
12
13/// Represents the parameters passed by the query string.
14pub struct Query<T>(pub T);
15
16impl<T> Deref for Query<T> {
17    type Target = T;
18
19    fn deref(&self) -> &Self::Target {
20        &self.0
21    }
22}
23
24impl<T> DerefMut for Query<T> {
25    fn deref_mut(&mut self) -> &mut Self::Target {
26        &mut self.0
27    }
28}
29
30impl<'a, T: ParseFromParameter> ApiExtractor<'a> for Query<T> {
31    const TYPES: &'static [ApiExtractorType] = &[ApiExtractorType::Parameter];
32    const PARAM_IS_REQUIRED: bool = T::IS_REQUIRED;
33
34    type ParamType = T;
35    type ParamRawType = T::RawValueType;
36
37    fn register(registry: &mut Registry) {
38        T::register(registry);
39    }
40
41    fn param_in() -> Option<MetaParamIn> {
42        Some(MetaParamIn::Query)
43    }
44
45    fn param_schema_ref() -> Option<MetaSchemaRef> {
46        Some(T::schema_ref())
47    }
48
49    fn param_raw_type(&self) -> Option<&Self::ParamRawType> {
50        self.0.as_raw_value()
51    }
52
53    async fn from_request(
54        request: &'a Request,
55        _body: &mut RequestBody,
56        param_opts: ExtractParamOptions<Self::ParamType>,
57    ) -> Result<Self> {
58        let mut values = request
59            .extensions()
60            .get::<UrlQuery>()
61            .unwrap()
62            .get_all(param_opts.name)
63            .peekable();
64
65        match &param_opts.default_value {
66            Some(default_value) if values.peek().is_none() => {
67                return Ok(Self(default_value()));
68            }
69            _ => {}
70        }
71
72        if param_opts.explode {
73            ParseFromParameter::parse_from_parameters(values)
74                .map(Self)
75                .map_err(|err| {
76                    ParseParamError {
77                        name: param_opts.name,
78                        reason: err.into_message(),
79                    }
80                    .into()
81                })
82        } else {
83            let values = values.next().unwrap().split(',').map(|v| v.trim());
84            ParseFromParameter::parse_from_parameters(values)
85                .map(Self)
86                .map_err(|err| {
87                    ParseParamError {
88                        name: param_opts.name,
89                        reason: err.into_message(),
90                    }
91                    .into()
92                })
93        }
94    }
95}