requiem_http/
message.rs

1use std::cell::{Ref, RefCell, RefMut};
2use std::net;
3use std::rc::Rc;
4
5use bitflags::bitflags;
6use copyless::BoxHelper;
7
8use crate::extensions::Extensions;
9use crate::header::HeaderMap;
10use crate::http::{header, Method, StatusCode, Uri, Version};
11
12/// Represents various types of connection
13#[derive(Copy, Clone, PartialEq, Debug)]
14pub enum ConnectionType {
15    /// Close connection after response
16    Close,
17    /// Keep connection alive after response
18    KeepAlive,
19    /// Connection is upgraded to different type
20    Upgrade,
21}
22
23bitflags! {
24    pub(crate) struct Flags: u8 {
25        const CLOSE       = 0b0000_0001;
26        const KEEP_ALIVE  = 0b0000_0010;
27        const UPGRADE     = 0b0000_0100;
28        const EXPECT      = 0b0000_1000;
29        const NO_CHUNKING = 0b0001_0000;
30        const CAMEL_CASE  = 0b0010_0000;
31    }
32}
33
34#[doc(hidden)]
35pub trait Head: Default + 'static {
36    fn clear(&mut self);
37
38    fn pool() -> &'static MessagePool<Self>;
39}
40
41#[derive(Debug)]
42pub struct RequestHead {
43    pub uri: Uri,
44    pub method: Method,
45    pub version: Version,
46    pub headers: HeaderMap,
47    pub extensions: RefCell<Extensions>,
48    pub peer_addr: Option<net::SocketAddr>,
49    flags: Flags,
50}
51
52impl Default for RequestHead {
53    fn default() -> RequestHead {
54        RequestHead {
55            uri: Uri::default(),
56            method: Method::default(),
57            version: Version::HTTP_11,
58            headers: HeaderMap::with_capacity(16),
59            flags: Flags::empty(),
60            peer_addr: None,
61            extensions: RefCell::new(Extensions::new()),
62        }
63    }
64}
65
66impl Head for RequestHead {
67    fn clear(&mut self) {
68        self.flags = Flags::empty();
69        self.headers.clear();
70        self.extensions.borrow_mut().clear();
71    }
72
73    fn pool() -> &'static MessagePool<Self> {
74        REQUEST_POOL.with(|p| *p)
75    }
76}
77
78impl RequestHead {
79    /// Message extensions
80    #[inline]
81    pub fn extensions(&self) -> Ref<'_, Extensions> {
82        self.extensions.borrow()
83    }
84
85    /// Mutable reference to a the message's extensions
86    #[inline]
87    pub fn extensions_mut(&self) -> RefMut<'_, Extensions> {
88        self.extensions.borrow_mut()
89    }
90
91    /// Read the message headers.
92    pub fn headers(&self) -> &HeaderMap {
93        &self.headers
94    }
95
96    /// Mutable reference to the message headers.
97    pub fn headers_mut(&mut self) -> &mut HeaderMap {
98        &mut self.headers
99    }
100
101    /// Is to uppercase headers with Camel-Case.
102    /// Befault is `false`
103    #[inline]
104    pub fn camel_case_headers(&self) -> bool {
105        self.flags.contains(Flags::CAMEL_CASE)
106    }
107
108    /// Set `true` to send headers which are uppercased with Camel-Case.
109    #[inline]
110    pub fn set_camel_case_headers(&mut self, val: bool) {
111        if val {
112            self.flags.insert(Flags::CAMEL_CASE);
113        } else {
114            self.flags.remove(Flags::CAMEL_CASE);
115        }
116    }
117
118    #[inline]
119    /// Set connection type of the message
120    pub fn set_connection_type(&mut self, ctype: ConnectionType) {
121        match ctype {
122            ConnectionType::Close => self.flags.insert(Flags::CLOSE),
123            ConnectionType::KeepAlive => self.flags.insert(Flags::KEEP_ALIVE),
124            ConnectionType::Upgrade => self.flags.insert(Flags::UPGRADE),
125        }
126    }
127
128    #[inline]
129    /// Connection type
130    pub fn connection_type(&self) -> ConnectionType {
131        if self.flags.contains(Flags::CLOSE) {
132            ConnectionType::Close
133        } else if self.flags.contains(Flags::KEEP_ALIVE) {
134            ConnectionType::KeepAlive
135        } else if self.flags.contains(Flags::UPGRADE) {
136            ConnectionType::Upgrade
137        } else if self.version < Version::HTTP_11 {
138            ConnectionType::Close
139        } else {
140            ConnectionType::KeepAlive
141        }
142    }
143
144    /// Connection upgrade status
145    pub fn upgrade(&self) -> bool {
146        if let Some(hdr) = self.headers().get(header::CONNECTION) {
147            if let Ok(s) = hdr.to_str() {
148                s.to_ascii_lowercase().contains("upgrade")
149            } else {
150                false
151            }
152        } else {
153            false
154        }
155    }
156
157    #[inline]
158    /// Get response body chunking state
159    pub fn chunked(&self) -> bool {
160        !self.flags.contains(Flags::NO_CHUNKING)
161    }
162
163    #[inline]
164    pub fn no_chunking(&mut self, val: bool) {
165        if val {
166            self.flags.insert(Flags::NO_CHUNKING);
167        } else {
168            self.flags.remove(Flags::NO_CHUNKING);
169        }
170    }
171
172    #[inline]
173    /// Request contains `EXPECT` header
174    pub fn expect(&self) -> bool {
175        self.flags.contains(Flags::EXPECT)
176    }
177
178    #[inline]
179    pub(crate) fn set_expect(&mut self) {
180        self.flags.insert(Flags::EXPECT);
181    }
182}
183
184#[derive(Debug)]
185pub enum RequestHeadType {
186    Owned(RequestHead),
187    Rc(Rc<RequestHead>, Option<HeaderMap>),
188}
189
190impl RequestHeadType {
191    pub fn extra_headers(&self) -> Option<&HeaderMap> {
192        match self {
193            RequestHeadType::Owned(_) => None,
194            RequestHeadType::Rc(_, headers) => headers.as_ref(),
195        }
196    }
197}
198
199impl AsRef<RequestHead> for RequestHeadType {
200    fn as_ref(&self) -> &RequestHead {
201        match self {
202            RequestHeadType::Owned(head) => &head,
203            RequestHeadType::Rc(head, _) => head.as_ref(),
204        }
205    }
206}
207
208impl From<RequestHead> for RequestHeadType {
209    fn from(head: RequestHead) -> Self {
210        RequestHeadType::Owned(head)
211    }
212}
213
214#[derive(Debug)]
215pub struct ResponseHead {
216    pub version: Version,
217    pub status: StatusCode,
218    pub headers: HeaderMap,
219    pub reason: Option<&'static str>,
220    pub(crate) extensions: RefCell<Extensions>,
221    flags: Flags,
222}
223
224impl ResponseHead {
225    /// Create new instance of `ResponseHead` type
226    #[inline]
227    pub fn new(status: StatusCode) -> ResponseHead {
228        ResponseHead {
229            status,
230            version: Version::default(),
231            headers: HeaderMap::with_capacity(12),
232            reason: None,
233            flags: Flags::empty(),
234            extensions: RefCell::new(Extensions::new()),
235        }
236    }
237
238    /// Message extensions
239    #[inline]
240    pub fn extensions(&self) -> Ref<'_, Extensions> {
241        self.extensions.borrow()
242    }
243
244    /// Mutable reference to a the message's extensions
245    #[inline]
246    pub fn extensions_mut(&self) -> RefMut<'_, Extensions> {
247        self.extensions.borrow_mut()
248    }
249
250    #[inline]
251    /// Read the message headers.
252    pub fn headers(&self) -> &HeaderMap {
253        &self.headers
254    }
255
256    #[inline]
257    /// Mutable reference to the message headers.
258    pub fn headers_mut(&mut self) -> &mut HeaderMap {
259        &mut self.headers
260    }
261
262    #[inline]
263    /// Set connection type of the message
264    pub fn set_connection_type(&mut self, ctype: ConnectionType) {
265        match ctype {
266            ConnectionType::Close => self.flags.insert(Flags::CLOSE),
267            ConnectionType::KeepAlive => self.flags.insert(Flags::KEEP_ALIVE),
268            ConnectionType::Upgrade => self.flags.insert(Flags::UPGRADE),
269        }
270    }
271
272    #[inline]
273    pub fn connection_type(&self) -> ConnectionType {
274        if self.flags.contains(Flags::CLOSE) {
275            ConnectionType::Close
276        } else if self.flags.contains(Flags::KEEP_ALIVE) {
277            ConnectionType::KeepAlive
278        } else if self.flags.contains(Flags::UPGRADE) {
279            ConnectionType::Upgrade
280        } else if self.version < Version::HTTP_11 {
281            ConnectionType::Close
282        } else {
283            ConnectionType::KeepAlive
284        }
285    }
286
287    #[inline]
288    /// Check if keep-alive is enabled
289    pub fn keep_alive(&self) -> bool {
290        self.connection_type() == ConnectionType::KeepAlive
291    }
292
293    #[inline]
294    /// Check upgrade status of this message
295    pub fn upgrade(&self) -> bool {
296        self.connection_type() == ConnectionType::Upgrade
297    }
298
299    /// Get custom reason for the response
300    #[inline]
301    pub fn reason(&self) -> &str {
302        if let Some(reason) = self.reason {
303            reason
304        } else {
305            self.status
306                .canonical_reason()
307                .unwrap_or("<unknown status code>")
308        }
309    }
310
311    #[inline]
312    pub(crate) fn ctype(&self) -> Option<ConnectionType> {
313        if self.flags.contains(Flags::CLOSE) {
314            Some(ConnectionType::Close)
315        } else if self.flags.contains(Flags::KEEP_ALIVE) {
316            Some(ConnectionType::KeepAlive)
317        } else if self.flags.contains(Flags::UPGRADE) {
318            Some(ConnectionType::Upgrade)
319        } else {
320            None
321        }
322    }
323
324    #[inline]
325    /// Get response body chunking state
326    pub fn chunked(&self) -> bool {
327        !self.flags.contains(Flags::NO_CHUNKING)
328    }
329
330    #[inline]
331    /// Set no chunking for payload
332    pub fn no_chunking(&mut self, val: bool) {
333        if val {
334            self.flags.insert(Flags::NO_CHUNKING);
335        } else {
336            self.flags.remove(Flags::NO_CHUNKING);
337        }
338    }
339}
340
341pub struct Message<T: Head> {
342    head: Rc<T>,
343}
344
345impl<T: Head> Message<T> {
346    /// Get new message from the pool of objects
347    pub fn new() -> Self {
348        T::pool().get_message()
349    }
350}
351
352impl<T: Head> Clone for Message<T> {
353    fn clone(&self) -> Self {
354        Message {
355            head: self.head.clone(),
356        }
357    }
358}
359
360impl<T: Head> std::ops::Deref for Message<T> {
361    type Target = T;
362
363    fn deref(&self) -> &Self::Target {
364        &self.head.as_ref()
365    }
366}
367
368impl<T: Head> std::ops::DerefMut for Message<T> {
369    fn deref_mut(&mut self) -> &mut Self::Target {
370        Rc::get_mut(&mut self.head).expect("Multiple copies exist")
371    }
372}
373
374impl<T: Head> Drop for Message<T> {
375    fn drop(&mut self) {
376        if Rc::strong_count(&self.head) == 1 {
377            T::pool().release(self.head.clone());
378        }
379    }
380}
381
382pub(crate) struct BoxedResponseHead {
383    head: Option<Box<ResponseHead>>,
384}
385
386impl BoxedResponseHead {
387    /// Get new message from the pool of objects
388    pub fn new(status: StatusCode) -> Self {
389        RESPONSE_POOL.with(|p| p.get_message(status))
390    }
391
392    pub(crate) fn take(&mut self) -> Self {
393        BoxedResponseHead {
394            head: self.head.take(),
395        }
396    }
397}
398
399impl std::ops::Deref for BoxedResponseHead {
400    type Target = ResponseHead;
401
402    fn deref(&self) -> &Self::Target {
403        self.head.as_ref().unwrap()
404    }
405}
406
407impl std::ops::DerefMut for BoxedResponseHead {
408    fn deref_mut(&mut self) -> &mut Self::Target {
409        self.head.as_mut().unwrap()
410    }
411}
412
413impl Drop for BoxedResponseHead {
414    fn drop(&mut self) {
415        if let Some(head) = self.head.take() {
416            RESPONSE_POOL.with(move |p| p.release(head))
417        }
418    }
419}
420
421#[doc(hidden)]
422/// Request's objects pool
423pub struct MessagePool<T: Head>(RefCell<Vec<Rc<T>>>);
424
425#[doc(hidden)]
426#[allow(clippy::vec_box)]
427/// Request's objects pool
428pub struct BoxedResponsePool(RefCell<Vec<Box<ResponseHead>>>);
429
430thread_local!(static REQUEST_POOL: &'static MessagePool<RequestHead> = MessagePool::<RequestHead>::create());
431thread_local!(static RESPONSE_POOL: &'static BoxedResponsePool = BoxedResponsePool::create());
432
433impl<T: Head> MessagePool<T> {
434    fn create() -> &'static MessagePool<T> {
435        let pool = MessagePool(RefCell::new(Vec::with_capacity(128)));
436        Box::leak(Box::new(pool))
437    }
438
439    /// Get message from the pool
440    #[inline]
441    fn get_message(&'static self) -> Message<T> {
442        if let Some(mut msg) = self.0.borrow_mut().pop() {
443            if let Some(r) = Rc::get_mut(&mut msg) {
444                r.clear();
445            }
446            Message { head: msg }
447        } else {
448            Message {
449                head: Rc::new(T::default()),
450            }
451        }
452    }
453
454    #[inline]
455    /// Release request instance
456    fn release(&self, msg: Rc<T>) {
457        let v = &mut self.0.borrow_mut();
458        if v.len() < 128 {
459            v.push(msg);
460        }
461    }
462}
463
464impl BoxedResponsePool {
465    fn create() -> &'static BoxedResponsePool {
466        let pool = BoxedResponsePool(RefCell::new(Vec::with_capacity(128)));
467        Box::leak(Box::new(pool))
468    }
469
470    /// Get message from the pool
471    #[inline]
472    fn get_message(&'static self, status: StatusCode) -> BoxedResponseHead {
473        if let Some(mut head) = self.0.borrow_mut().pop() {
474            head.reason = None;
475            head.status = status;
476            head.headers.clear();
477            head.flags = Flags::empty();
478            BoxedResponseHead { head: Some(head) }
479        } else {
480            BoxedResponseHead {
481                head: Some(Box::alloc().init(ResponseHead::new(status))),
482            }
483        }
484    }
485
486    #[inline]
487    /// Release request instance
488    fn release(&self, msg: Box<ResponseHead>) {
489        let v = &mut self.0.borrow_mut();
490        if v.len() < 128 {
491            msg.extensions.borrow_mut().clear();
492            v.push(msg);
493        }
494    }
495}