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 pub(crate) fn set_path_params(&mut self, params: PathParams) {
186 self.path_params = params;
187 }
188
189 #[cfg(any(test, feature = "test-utils"))]
193 pub fn from_http_request<B>(req: http::Request<B>, body: Bytes) -> Self {
194 let (parts, _) = req.into_parts();
195 Self {
196 parts,
197 body: BodyVariant::Buffered(body),
198 state: Arc::new(Extensions::new()),
199 path_params: PathParams::new(),
200 }
201 }
202 pub fn try_clone(&self) -> Option<Self> {
209 let mut builder = http::Request::builder()
210 .method(self.method().clone())
211 .uri(self.uri().clone())
212 .version(self.version());
213
214 if let Some(headers) = builder.headers_mut() {
215 *headers = self.headers().clone();
216 }
217
218 let req = builder.body(()).ok()?;
219 let (parts, _) = req.into_parts();
220
221 let new_body = match &self.body {
222 BodyVariant::Buffered(b) => BodyVariant::Buffered(b.clone()),
223 BodyVariant::Streaming(_) => return None, BodyVariant::Consumed => return None,
225 };
226
227 Some(Self {
228 parts,
229 body: new_body,
230 state: self.state.clone(),
231 path_params: self.path_params.clone(),
232 })
233 }
234}
235
236impl std::fmt::Debug for Request {
237 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
238 f.debug_struct("Request")
239 .field("method", &self.parts.method)
240 .field("uri", &self.parts.uri)
241 .field("version", &self.parts.version)
242 .finish()
243 }
244}