1use poem::error::ResponseError;
19use poem::http::StatusCode;
20use poem::{FromRequest, Request, RequestBody, Result};
21use std::fmt;
22use std::ops::{Deref, DerefMut};
23use vld::schema::VldParse;
24
25#[derive(Debug)]
31pub struct VldPoemError(pub serde_json::Value);
32
33impl fmt::Display for VldPoemError {
34 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35 write!(f, "{}", self.0)
36 }
37}
38
39impl std::error::Error for VldPoemError {}
40
41impl ResponseError for VldPoemError {
42 fn status(&self) -> StatusCode {
43 StatusCode::UNPROCESSABLE_ENTITY
44 }
45
46 fn as_response(&self) -> poem::Response {
47 poem::Response::builder()
48 .status(StatusCode::UNPROCESSABLE_ENTITY)
49 .content_type("application/json")
50 .body(serde_json::to_string(&self.0).unwrap_or_default())
51 }
52}
53
54#[derive(Debug, Clone)]
60pub struct VldJson<T>(pub T);
61
62impl<T> Deref for VldJson<T> {
63 type Target = T;
64 fn deref(&self) -> &T {
65 &self.0
66 }
67}
68
69impl<T> DerefMut for VldJson<T> {
70 fn deref_mut(&mut self) -> &mut T {
71 &mut self.0
72 }
73}
74
75impl<'a, T: VldParse + Send + Sync + 'static> FromRequest<'a> for VldJson<T> {
76 async fn from_request(_req: &'a Request, body: &mut RequestBody) -> Result<Self> {
77 let bytes = body.take()?.into_bytes().await?;
78 let value: serde_json::Value = serde_json::from_slice(&bytes)
79 .map_err(|e| VldPoemError(format_json_parse_error(&e.to_string())))?;
80
81 T::vld_parse_value(&value)
82 .map(VldJson)
83 .map_err(|e| VldPoemError(format_vld_error(&e)).into())
84 }
85}
86
87#[derive(Debug, Clone)]
93pub struct VldQuery<T>(pub T);
94
95impl<T> Deref for VldQuery<T> {
96 type Target = T;
97 fn deref(&self) -> &T {
98 &self.0
99 }
100}
101
102impl<T> DerefMut for VldQuery<T> {
103 fn deref_mut(&mut self) -> &mut T {
104 &mut self.0
105 }
106}
107
108impl<'a, T: VldParse + Send + Sync + 'static> FromRequest<'a> for VldQuery<T> {
109 async fn from_request(req: &'a Request, _body: &mut RequestBody) -> Result<Self> {
110 let qs = req.uri().query().unwrap_or("");
111 let map = parse_query_to_json(qs);
112 let value = serde_json::Value::Object(map);
113
114 T::vld_parse_value(&value)
115 .map(VldQuery)
116 .map_err(|e| VldPoemError(format_vld_error(&e)).into())
117 }
118}
119
120#[derive(Debug, Clone)]
126pub struct VldForm<T>(pub T);
127
128impl<T> Deref for VldForm<T> {
129 type Target = T;
130 fn deref(&self) -> &T {
131 &self.0
132 }
133}
134
135impl<T> DerefMut for VldForm<T> {
136 fn deref_mut(&mut self) -> &mut T {
137 &mut self.0
138 }
139}
140
141impl<'a, T: VldParse + Send + Sync + 'static> FromRequest<'a> for VldForm<T> {
142 async fn from_request(_req: &'a Request, body: &mut RequestBody) -> Result<Self> {
143 let bytes = body.take()?.into_bytes().await?;
144 let body_str = String::from_utf8(bytes.to_vec())
145 .map_err(|_| VldPoemError(vld_http_common::format_utf8_error()))?;
146
147 let map = parse_query_to_json(&body_str);
148 let value = serde_json::Value::Object(map);
149
150 T::vld_parse_value(&value)
151 .map(VldForm)
152 .map_err(|e| VldPoemError(format_vld_error(&e)).into())
153 }
154}
155
156use vld_http_common::{
161 coerce_value, cookies_to_json, format_json_parse_error, format_vld_error,
162 parse_query_string as parse_query_to_json,
163};
164
165#[derive(Debug, Clone)]
173pub struct VldPath<T>(pub T);
174
175impl<T> Deref for VldPath<T> {
176 type Target = T;
177 fn deref(&self) -> &T {
178 &self.0
179 }
180}
181
182impl<T> DerefMut for VldPath<T> {
183 fn deref_mut(&mut self) -> &mut T {
184 &mut self.0
185 }
186}
187
188impl<'a, T: VldParse + Send + Sync + 'static> FromRequest<'a> for VldPath<T> {
189 async fn from_request(req: &'a Request, _body: &mut RequestBody) -> Result<Self> {
190 let params = req.params::<Vec<(String, String)>>().unwrap_or_default();
191
192 let mut map = serde_json::Map::new();
193 for (k, v) in ¶ms {
194 map.insert(k.clone(), coerce_value(v));
195 }
196 let value = serde_json::Value::Object(map);
197
198 T::vld_parse_value(&value)
199 .map(VldPath)
200 .map_err(|e| VldPoemError(format_vld_error(&e)).into())
201 }
202}
203
204#[derive(Debug, Clone)]
213pub struct VldHeaders<T>(pub T);
214
215impl<T> Deref for VldHeaders<T> {
216 type Target = T;
217 fn deref(&self) -> &T {
218 &self.0
219 }
220}
221
222impl<T> DerefMut for VldHeaders<T> {
223 fn deref_mut(&mut self) -> &mut T {
224 &mut self.0
225 }
226}
227
228impl<'a, T: VldParse + Send + Sync + 'static> FromRequest<'a> for VldHeaders<T> {
229 async fn from_request(req: &'a Request, _body: &mut RequestBody) -> Result<Self> {
230 let mut map = serde_json::Map::new();
231 for (name, value) in req.headers().iter() {
232 let key = name.as_str().to_lowercase().replace('-', "_");
233 if let Ok(v) = value.to_str() {
234 map.insert(key, coerce_value(v));
235 }
236 }
237 let value = serde_json::Value::Object(map);
238
239 T::vld_parse_value(&value)
240 .map(VldHeaders)
241 .map_err(|e| VldPoemError(format_vld_error(&e)).into())
242 }
243}
244
245#[derive(Debug, Clone)]
253pub struct VldCookie<T>(pub T);
254
255impl<T> Deref for VldCookie<T> {
256 type Target = T;
257 fn deref(&self) -> &T {
258 &self.0
259 }
260}
261
262impl<T> DerefMut for VldCookie<T> {
263 fn deref_mut(&mut self) -> &mut T {
264 &mut self.0
265 }
266}
267
268impl<'a, T: VldParse + Send + Sync + 'static> FromRequest<'a> for VldCookie<T> {
269 async fn from_request(req: &'a Request, _body: &mut RequestBody) -> Result<Self> {
270 let cookie_header = req
271 .headers()
272 .get("cookie")
273 .and_then(|v| v.to_str().ok())
274 .unwrap_or("");
275
276 let value = cookies_to_json(cookie_header);
277
278 T::vld_parse_value(&value)
279 .map(VldCookie)
280 .map_err(|e| VldPoemError(format_vld_error(&e)).into())
281 }
282}
283
284pub mod prelude {
286 pub use crate::{VldCookie, VldForm, VldHeaders, VldJson, VldPath, VldQuery};
287 pub use vld::prelude::*;
288}