teo_runtime/request/
request.rs1use 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 { }