poem_openapi/param/
cookie.rs

1use std::ops::{Deref, DerefMut};
2
3use poem::{Request, RequestBody, Result};
4
5use crate::{
6    error::ParseParamError,
7    registry::{MetaParamIn, MetaSchemaRef, Registry},
8    types::ParseFromParameter,
9    ApiExtractor, ApiExtractorType, ExtractParamOptions,
10};
11
12/// Represents the parameters passed by the cookie.
13pub struct Cookie<T>(pub T);
14
15impl<T> Deref for Cookie<T> {
16    type Target = T;
17
18    fn deref(&self) -> &Self::Target {
19        &self.0
20    }
21}
22
23impl<T> DerefMut for Cookie<T> {
24    fn deref_mut(&mut self) -> &mut Self::Target {
25        &mut self.0
26    }
27}
28
29impl<'a, T: ParseFromParameter> ApiExtractor<'a> for Cookie<T> {
30    const TYPES: &'static [ApiExtractorType] = &[ApiExtractorType::Parameter];
31    const PARAM_IS_REQUIRED: bool = T::IS_REQUIRED;
32
33    type ParamType = T;
34    type ParamRawType = T::RawValueType;
35
36    fn register(registry: &mut Registry) {
37        T::register(registry);
38    }
39
40    fn param_in() -> Option<MetaParamIn> {
41        Some(MetaParamIn::Cookie)
42    }
43
44    fn param_schema_ref() -> Option<MetaSchemaRef> {
45        Some(T::schema_ref())
46    }
47
48    fn param_raw_type(&self) -> Option<&Self::ParamRawType> {
49        self.0.as_raw_value()
50    }
51
52    async fn from_request(
53        request: &'a Request,
54        _body: &mut RequestBody,
55        param_opts: ExtractParamOptions<Self::ParamType>,
56    ) -> Result<Self> {
57        let value = request
58            .cookie()
59            .get(param_opts.name)
60            .as_ref()
61            .map(|cookie| cookie.value_str().to_string());
62        let value = match (value, &param_opts.default_value) {
63            (Some(value), _) => Some(value),
64            (None, Some(default_value)) => return Ok(Self(default_value())),
65            (None, _) => None,
66        };
67
68        ParseFromParameter::parse_from_parameters(value.as_deref())
69            .map(Self)
70            .map_err(|err| {
71                ParseParamError {
72                    name: param_opts.name,
73                    reason: err.into_message(),
74                }
75                .into()
76            })
77    }
78}
79
80/// Represents the parameters passed by the private cookie.
81pub struct CookiePrivate<T>(pub T);
82
83impl<T> Deref for CookiePrivate<T> {
84    type Target = T;
85
86    fn deref(&self) -> &Self::Target {
87        &self.0
88    }
89}
90
91impl<T> DerefMut for CookiePrivate<T> {
92    fn deref_mut(&mut self) -> &mut Self::Target {
93        &mut self.0
94    }
95}
96
97impl<'a, T: ParseFromParameter> ApiExtractor<'a> for CookiePrivate<T> {
98    const TYPES: &'static [ApiExtractorType] = &[ApiExtractorType::Parameter];
99    const PARAM_IS_REQUIRED: bool = T::IS_REQUIRED;
100
101    type ParamType = T;
102    type ParamRawType = T::RawValueType;
103
104    fn register(registry: &mut Registry) {
105        T::register(registry);
106    }
107
108    fn param_in() -> Option<MetaParamIn> {
109        Some(MetaParamIn::Cookie)
110    }
111
112    fn param_schema_ref() -> Option<MetaSchemaRef> {
113        Some(T::schema_ref())
114    }
115
116    fn param_raw_type(&self) -> Option<&Self::ParamRawType> {
117        self.0.as_raw_value()
118    }
119
120    async fn from_request(
121        request: &'a Request,
122        _body: &mut RequestBody,
123        param_opts: ExtractParamOptions<Self::ParamType>,
124    ) -> Result<Self> {
125        let value = request
126            .cookie()
127            .private()
128            .get(param_opts.name)
129            .as_ref()
130            .map(|cookie| cookie.value_str().to_string());
131        let value = match (value, &param_opts.default_value) {
132            (Some(value), _) => Some(value),
133            (None, Some(default_value)) => return Ok(Self(default_value())),
134            (None, _) => None,
135        };
136
137        ParseFromParameter::parse_from_parameters(value.as_deref())
138            .map(Self)
139            .map_err(|err| {
140                ParseParamError {
141                    name: param_opts.name,
142                    reason: err.into_message(),
143                }
144                .into()
145            })
146    }
147}
148
149/// Represents the parameters passed by the signed cookie.
150pub struct CookieSigned<T>(pub T);
151
152impl<T> Deref for CookieSigned<T> {
153    type Target = T;
154
155    fn deref(&self) -> &Self::Target {
156        &self.0
157    }
158}
159
160impl<T> DerefMut for CookieSigned<T> {
161    fn deref_mut(&mut self) -> &mut Self::Target {
162        &mut self.0
163    }
164}
165
166impl<'a, T: ParseFromParameter> ApiExtractor<'a> for CookieSigned<T> {
167    const TYPES: &'static [ApiExtractorType] = &[ApiExtractorType::Parameter];
168    const PARAM_IS_REQUIRED: bool = T::IS_REQUIRED;
169
170    type ParamType = T;
171    type ParamRawType = T::RawValueType;
172
173    fn register(registry: &mut Registry) {
174        T::register(registry);
175    }
176
177    fn param_in() -> Option<MetaParamIn> {
178        Some(MetaParamIn::Cookie)
179    }
180
181    fn param_schema_ref() -> Option<MetaSchemaRef> {
182        Some(T::schema_ref())
183    }
184
185    fn param_raw_type(&self) -> Option<&Self::ParamRawType> {
186        self.0.as_raw_value()
187    }
188
189    async fn from_request(
190        request: &'a Request,
191        _body: &mut RequestBody,
192        param_opts: ExtractParamOptions<Self::ParamType>,
193    ) -> Result<Self> {
194        let value = request
195            .cookie()
196            .signed()
197            .get(param_opts.name)
198            .as_ref()
199            .map(|cookie| cookie.value_str().to_string());
200        let value = match (value, &param_opts.default_value) {
201            (Some(value), _) => Some(value),
202            (None, Some(default_value)) => return Ok(Self(default_value())),
203            (None, _) => None,
204        };
205
206        ParseFromParameter::parse_from_parameters(value.as_deref())
207            .map(Self)
208            .map_err(|err| {
209                ParseParamError {
210                    name: param_opts.name,
211                    reason: err.into_message(),
212                }
213                .into()
214            })
215    }
216}