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