chuchi_core/request/
mod.rs1mod builder;
2pub use builder::RequestBuilder;
3
4use crate::body::Body;
5#[cfg(feature = "json")]
6use crate::header::CONTENT_TYPE;
7use crate::header::{RequestHeader, Uri};
8
9use std::time::Duration;
10
11#[derive(Debug)]
13pub struct Request {
14 pub header: RequestHeader,
15 pub body: Body,
16}
17
18impl Request {
19 pub fn new(header: RequestHeader, body: Body) -> Self {
21 Self { header, body }
22 }
23
24 pub fn builder(uri: Uri) -> RequestBuilder {
26 RequestBuilder::new(uri)
27 }
28
29 pub fn take_body(&mut self) -> Body {
31 self.body.take()
32 }
33
34 pub fn header(&self) -> &RequestHeader {
36 &self.header
37 }
38
39 pub fn set_size_limit(&mut self, size: Option<usize>) {
41 self.body.set_size_limit(size)
42 }
43
44 pub fn set_timeout(&mut self, timeout: Option<Duration>) {
46 self.body.set_timeout(timeout)
47 }
48
49 #[cfg(feature = "json")]
55 #[cfg_attr(docsrs, doc(cfg(feature = "json")))]
56 pub async fn deserialize<D>(&mut self) -> Result<D, DeserializeError>
57 where
58 D: serde::de::DeserializeOwned + Send + 'static,
59 {
60 use crate::header::Mime;
61
62 let raw_content_type = self
66 .header()
67 .value(CONTENT_TYPE)
68 .ok_or(DeserializeError::NoContentType)?;
69 let mime: Mime = raw_content_type.trim().parse().map_err(|_| {
70 DeserializeError::UnknownContentType(raw_content_type.to_string())
71 })?;
72
73 if mime != Mime::JSON {
74 return Err(DeserializeError::WrongMimeType(mime));
75 }
76
77 self.body
79 .take()
80 .deserialize()
81 .await
82 .map_err(DeserializeError::Json)
83 }
84
85 #[cfg(feature = "query")]
86 #[cfg_attr(docsrs, doc(cfg(feature = "query")))]
87 pub fn deserialize_query<D>(&self) -> Result<D, DeserializeError>
88 where
89 D: serde::de::DeserializeOwned + Send + 'static,
90 {
91 let query = self.header().uri().query().unwrap_or("");
92
93 serde_urlencoded::from_str(query)
94 .map_err(DeserializeError::UrlEncoded)
95 }
96}
97
98#[cfg(any(feature = "json", feature = "query"))]
99mod serde_error {
100 use crate::header::Mime;
101
102 use std::fmt;
103
104 #[derive(Debug)]
105 #[non_exhaustive]
106 pub enum DeserializeError {
107 NoContentType,
108 UnknownContentType(String),
109 WrongMimeType(Mime),
110 #[cfg(feature = "json")]
111 Json(serde_json::Error),
112 #[cfg(feature = "query")]
113 UrlEncoded(serde::de::value::Error),
114 }
115
116 impl fmt::Display for DeserializeError {
117 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
118 write!(f, "Failed to deserialize request {:?}", self)
119 }
120 }
121
122 impl std::error::Error for DeserializeError {}
123
124 #[derive(Debug)]
125 #[non_exhaustive]
126 pub enum SerializeError {
127 #[cfg(feature = "json")]
128 Json(serde_json::Error),
129 #[cfg(feature = "query")]
130 UrlEncoded(serde_urlencoded::ser::Error),
131 }
132
133 impl fmt::Display for SerializeError {
134 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
135 write!(f, "Failed to serialize request {:?}", self)
136 }
137 }
138
139 impl std::error::Error for SerializeError {}
140}
141
142#[cfg(any(feature = "json", feature = "query"))]
143pub use serde_error::*;
144
145#[cfg(test)]
146mod tests {
147 #[allow(unused_imports)]
148 use super::*;
149
150 #[cfg(feature = "query")]
151 #[tokio::test]
152 async fn deserialize_query() {
153 let uri = "http://localhost:8080/?a=1&b=2";
154 let req = Request::builder(uri.parse().unwrap()).build();
155
156 #[derive(serde::Deserialize)]
157 struct Query {
158 a: String,
159 b: String,
160 c: Option<String>,
161 }
162
163 let query: Query = req.deserialize_query().unwrap();
164 assert_eq!(query.a, "1");
165 assert_eq!(query.b, "2");
166 assert_eq!(query.c, None);
167 }
168}