teo_runtime/request/
request.rs

1use std::cell::RefCell;
2use std::fmt::{Debug, Formatter};
3use std::str::FromStr;
4use std::sync::Arc;
5use hyper::{self, Method, Uri, Version};
6use teo_result::{Error, Result};
7use history_box::HistoryBox;
8use http_body_util::Full;
9use hyper::body::Incoming;
10use hyper::header::CONTENT_TYPE;
11use hyper::http::uri::Scheme;
12use indexmap::IndexMap;
13use bytes::Bytes;
14use crate::connection::transaction;
15use crate::handler::r#match::HandlerMatch;
16use crate::cookies::Cookies;
17use crate::headers::headers::Headers;
18use crate::request::extract::ExtractFromRequest;
19use crate::request::local_objects::LocalObjects;
20use crate::request::local_values::LocalValues;
21use crate::Value;
22
23#[derive(Clone)]
24pub struct Request {
25    inner: Arc<Inner>,
26}
27
28struct Inner {
29    method: HistoryBox<Method>,
30    uri: HistoryBox<Uri>,
31    version: HistoryBox<Version>,
32    headers: HistoryBox<Headers>,
33    transaction_ctx: transaction::Ctx,
34    cookies: HistoryBox<Cookies>,
35    handler_match: HistoryBox<HandlerMatch>,
36    body_value: HistoryBox<Value>,
37    local_values: LocalValues,
38    local_objects: LocalObjects,
39    incoming: RefCell<Option<Incoming>>,
40    incoming_bytes: RefCell<Option<Full<Bytes>>>,
41}
42
43impl Request {
44
45    pub fn new(hyper_request: hyper::Request<Incoming>, transaction_ctx: transaction::Ctx) -> Self {
46        let (parts, incoming) = hyper_request.into_parts();
47        Self {
48            inner: Arc::new(Inner {
49                method: HistoryBox::new_with(parts.method),
50                uri: HistoryBox::new_with(parts.uri),
51                version: HistoryBox::new_with(parts.version),
52                headers: HistoryBox::new_with(Headers::from(parts.headers)),
53                incoming: RefCell::new(Some(incoming)),
54                incoming_bytes: RefCell::new(None),
55                transaction_ctx,
56                cookies: HistoryBox::new(),
57                handler_match: HistoryBox::new(),
58                body_value: HistoryBox::new(),
59                local_values: LocalValues::new(),
60                local_objects: LocalObjects::new(),
61            })
62        }
63    }
64
65    pub fn new_for_test(hyper_request: hyper::Request<Full<Bytes>>, transaction_ctx: transaction::Ctx) -> Self {
66        let (parts, incoming) = hyper_request.into_parts();
67        Self {
68            inner: Arc::new(Inner {
69                method: HistoryBox::new_with(parts.method),
70                uri: HistoryBox::new_with(parts.uri),
71                version: HistoryBox::new_with(parts.version),
72                headers: HistoryBox::new_with(Headers::from(parts.headers)),
73                incoming: RefCell::new(None),
74                incoming_bytes: RefCell::new(Some(incoming)),
75                transaction_ctx,
76                cookies: HistoryBox::new(),
77                handler_match: HistoryBox::new(),
78                body_value: HistoryBox::new(),
79                local_values: LocalValues::new(),
80                local_objects: LocalObjects::new(),
81            })
82        }
83    }
84
85    #[inline(always)]
86    pub fn version(&self) -> Version {
87        *self.inner.version.get().unwrap()
88    }
89
90    #[inline(always)]
91    pub fn set_version(&self, version: Version) {
92        self.inner.version.set(version);
93    }
94
95    #[inline(always)]
96    pub fn method(&self) -> &Method {
97        self.inner.method.get().unwrap()
98    }
99
100    #[inline(always)]
101    pub fn set_method(&self, method: Method) {
102        self.inner.method.set(method);
103    }
104
105    #[inline(always)]
106    pub fn uri(&self) -> &Uri {
107        self.inner.uri.get().unwrap()
108    }
109
110    #[inline(always)]
111    pub fn set_uri(&self, uri: Uri) {
112        self.inner.uri.set(uri);
113    }
114
115    pub fn set_uri_string(&self, uri: &str) -> Result<()> {
116        self.inner.uri.set(Uri::from_str(uri)?);
117        Ok(())
118    }
119
120    #[inline(always)]
121    pub fn uri_string(&self) -> String {
122        self.uri().to_string()
123    }
124
125    #[inline(always)]
126    pub fn scheme(&self) -> Option<&Scheme> {
127        self.uri().scheme()
128    }
129
130    #[inline(always)]
131    pub fn scheme_str(&self) -> Option<&str> {
132        self.uri().scheme_str()
133    }
134
135    #[inline(always)]
136    pub fn host(&self) -> Option<&str> {
137        self.uri().host()
138    }
139
140    #[inline(always)]
141    pub fn path(&self) -> &str {
142        self.uri().path()
143    }
144
145    #[inline(always)]
146    pub fn query(&self) -> Option<&str> {
147        self.uri().query()
148    }
149
150    pub fn content_type(&self) -> Result<Option<String>> {
151        if let Some(value) = self.headers().get(CONTENT_TYPE.as_str())? {
152            Ok(Some(value))
153        } else {
154            Ok(None)
155        }
156    }
157
158    pub fn headers(&self) -> Headers {
159        self.inner.headers.get().unwrap().clone()
160    }
161
162    pub fn set_headers(&self, headers: Headers) {
163        self.inner.headers.set(headers);
164    }
165
166    pub fn cookies(&self) -> Result<&Cookies> {
167        if self.inner.cookies.get().is_none() {
168            self.parse_cookies()
169        } else {
170            Ok(self.inner.cookies.get().unwrap())
171        }
172    }
173
174    pub fn set_cookies(&self, cookies: Cookies) {
175        self.inner.cookies.set(cookies);
176    }
177
178    pub fn handler_match(&self) -> Result<&HandlerMatch> {
179        match self.inner.handler_match.get() {
180            Some(handler_match) => Ok(handler_match),
181            None => Err(Error::internal_server_error_message("handler match is accessed while it is unavailable")),
182        }
183    }
184
185    pub fn set_handler_match(&self, handler_match: HandlerMatch) {
186        self.inner.handler_match.set(handler_match);
187    }
188
189    pub fn captures(&self) -> Result<&IndexMap<String, String>> {
190        Ok(self.handler_match()?.captures())
191    }
192
193    pub fn body_value(&self) -> Result<&Value> {
194        match self.inner.body_value.get() {
195            Some(value) => Ok(value),
196            None => Err(Error::internal_server_error_message("request body value is accessed while it is unavailable")),
197        }
198    }
199
200    pub fn set_body_value(&self, value: Value) {
201        self.inner.body_value.set(value)
202    }
203
204    pub fn transaction_ctx(&self) -> transaction::Ctx {
205        self.inner.transaction_ctx.clone()
206    }
207
208    pub fn local_values(&self) -> &LocalValues {
209        &self.inner.local_values
210    }
211
212    pub fn local_objects(&self) -> &LocalObjects {
213        &self.inner.local_objects
214    }
215
216    pub fn take_incoming(&self) -> Option<Incoming> {
217        self.inner.incoming.replace(None)
218    }
219
220    pub fn take_incoming_bytes_for_test(&self) -> Option<Full<Bytes>> {
221        self.inner.incoming_bytes.replace(None)
222    }
223
224    pub fn clone_hyper_request_for_file_processing(&self) -> hyper::Request<()> {
225        let mut request = hyper::Request::builder()
226            .method(self.inner.method.get().unwrap().clone())
227            .uri(self.inner.uri.get().unwrap().clone())
228            .version(self.inner.version.get().unwrap().clone())
229            .body(())
230            .unwrap();
231        self.headers().extend_to(request.headers_mut());
232        request
233    }
234
235    fn parse_cookies(&self) -> Result<&Cookies> {
236        self.inner.cookies.set(Cookies::from_request_headers(&self.headers())?);
237        Ok(self.inner.cookies.get().unwrap())
238    }
239}
240
241impl Debug for Request {
242
243    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
244        let mut debug_struct = f.debug_struct("Request");
245        debug_struct.field("version", self.inner.version.get().unwrap());
246        debug_struct.field("method", &self.inner.method.get().unwrap());
247        debug_struct.field("uri", &self.inner.uri.get().unwrap());
248        debug_struct.field("headers", &self.inner.headers);
249        debug_struct.finish()
250    }
251}
252
253impl ExtractFromRequest for Request {
254    fn extract(request: &Request) -> Self {
255        request.clone()
256    }
257}
258
259unsafe impl Send for Request { }
260unsafe impl Sync for Request { }