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