poem_openapi/param/
query.rs1use 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
13pub 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 ¶m_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}