1use crate::path_params::PathParams;
43use bytes::Bytes;
44use http::{request::Parts, Extensions, HeaderMap, Method, Uri, Version};
45use http_body_util::BodyExt;
46use hyper::body::Incoming;
47use std::sync::Arc;
48
49pub(crate) enum BodyVariant {
51 Buffered(Bytes),
52 Streaming(Incoming),
53 Consumed,
54}
55
56pub struct Request {
60 pub(crate) parts: Parts,
61 pub(crate) body: BodyVariant,
62 pub(crate) state: Arc<Extensions>,
63 pub(crate) path_params: PathParams,
64}
65
66impl Request {
67 pub(crate) fn new(
69 parts: Parts,
70 body: BodyVariant,
71 state: Arc<Extensions>,
72 path_params: PathParams,
73 ) -> Self {
74 Self {
75 parts,
76 body,
77 state,
78 path_params,
79 }
80 }
81
82 pub fn method(&self) -> &Method {
84 &self.parts.method
85 }
86
87 pub fn uri(&self) -> &Uri {
89 &self.parts.uri
90 }
91
92 pub fn version(&self) -> Version {
94 self.parts.version
95 }
96
97 pub fn headers(&self) -> &HeaderMap {
99 &self.parts.headers
100 }
101
102 pub fn extensions(&self) -> &Extensions {
104 &self.parts.extensions
105 }
106
107 pub fn extensions_mut(&mut self) -> &mut Extensions {
109 &mut self.parts.extensions
110 }
111
112 pub fn path(&self) -> &str {
114 self.parts.uri.path()
115 }
116
117 pub fn query_string(&self) -> Option<&str> {
119 self.parts.uri.query()
120 }
121
122 pub fn take_body(&mut self) -> Option<Bytes> {
127 match std::mem::replace(&mut self.body, BodyVariant::Consumed) {
128 BodyVariant::Buffered(bytes) => Some(bytes),
129 other => {
130 self.body = other;
131 None
132 }
133 }
134 }
135
136 pub fn take_stream(&mut self) -> Option<Incoming> {
138 match std::mem::replace(&mut self.body, BodyVariant::Consumed) {
139 BodyVariant::Streaming(stream) => Some(stream),
140 other => {
141 self.body = other;
142 None
143 }
144 }
145 }
146
147 pub async fn load_body(&mut self) -> Result<(), crate::error::ApiError> {
153 let new_body = match std::mem::replace(&mut self.body, BodyVariant::Consumed) {
155 BodyVariant::Streaming(incoming) => {
156 let collected = incoming
157 .collect()
158 .await
159 .map_err(|e| crate::error::ApiError::bad_request(e.to_string()))?;
160 BodyVariant::Buffered(collected.to_bytes())
161 }
162 BodyVariant::Buffered(b) => BodyVariant::Buffered(b),
163 BodyVariant::Consumed => BodyVariant::Consumed,
164 };
165 self.body = new_body;
166 Ok(())
167 }
168
169 pub fn path_params(&self) -> &PathParams {
171 &self.path_params
172 }
173
174 pub fn path_param(&self, name: &str) -> Option<&String> {
176 self.path_params.get(name)
177 }
178
179 pub fn state(&self) -> &Arc<Extensions> {
181 &self.state
182 }
183
184 #[cfg(any(test, feature = "test-utils"))]
188 pub fn from_http_request<B>(req: http::Request<B>, body: Bytes) -> Self {
189 let (parts, _) = req.into_parts();
190 Self {
191 parts,
192 body: BodyVariant::Buffered(body),
193 state: Arc::new(Extensions::new()),
194 path_params: PathParams::new(),
195 }
196 }
197 pub fn try_clone(&self) -> Option<Self> {
204 let mut builder = http::Request::builder()
205 .method(self.method().clone())
206 .uri(self.uri().clone())
207 .version(self.version());
208
209 if let Some(headers) = builder.headers_mut() {
210 *headers = self.headers().clone();
211 }
212
213 let req = builder.body(()).ok()?;
214 let (parts, _) = req.into_parts();
215
216 let new_body = match &self.body {
217 BodyVariant::Buffered(b) => BodyVariant::Buffered(b.clone()),
218 BodyVariant::Streaming(_) => return None, BodyVariant::Consumed => return None,
220 };
221
222 Some(Self {
223 parts,
224 body: new_body,
225 state: self.state.clone(),
226 path_params: self.path_params.clone(),
227 })
228 }
229}
230
231impl std::fmt::Debug for Request {
232 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
233 f.debug_struct("Request")
234 .field("method", &self.parts.method)
235 .field("uri", &self.parts.uri)
236 .field("version", &self.parts.version)
237 .finish()
238 }
239}