tinyhttp_internal/
request.rs

1use std::{collections::HashMap, fmt::Display, mem};
2
3#[derive(Clone, Debug, Default)]
4pub struct Wildcard<T: Display> {
5    wildcard: T,
6}
7
8impl<T: Display> Display for Wildcard<T> {
9    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
10        write!(f, "{}", self.get_wildcard())
11    }
12}
13
14impl<T: Display> Wildcard<T> {
15    pub fn get_wildcard(&self) -> &T {
16        &self.wildcard
17    }
18}
19
20/// Struct containing data on a single request.
21///
22/// parsed_body which is a Option<String> that can contain the body as a String
23///
24/// body is used when the body of the request is not a String
25#[derive(Clone, Debug, Default)]
26pub struct Request {
27    raw_headers: HashMap<String, String>,
28    status_line: Vec<String>,
29    body: Vec<u8>,
30    wildcard: Option<String>,
31    is_http2: bool,
32}
33
34#[derive(Clone, Debug)]
35pub enum BodyType {
36    ASCII(String),
37    Bytes(Vec<u8>),
38}
39
40impl Request {
41    pub fn new(
42        body: Vec<u8>,
43        raw_headers: HashMap<String, String>,
44        status_line: Vec<String>,
45        wildcard: Option<String>,
46    ) -> Request {
47        Request {
48            body,
49            raw_headers,
50            status_line,
51            wildcard,
52            is_http2: false,
53        }
54    }
55
56    pub(crate) fn set_wildcard(&mut self, w: Option<String>) -> &Self {
57        self.wildcard = w;
58        self
59    }
60
61    /// Get request body as bytes
62    pub fn get_raw_body(&self) -> &[u8] {
63        &self.body
64    }
65
66    /// Get request body as a string
67    pub fn get_parsed_body(&self) -> Option<&str> {
68        if let Ok(s) = std::str::from_utf8(&self.body) {
69            Some(s)
70        } else {
71            None
72        }
73    }
74
75    /// Get request headers in a HashMap
76    pub fn get_headers(&self) -> &HashMap<String, String> {
77        #[cfg(feature = "log")]
78        log::trace!("Headers: {:#?}", self.raw_headers);
79
80        &self.raw_headers
81    }
82
83    /// Get status line of request
84    pub fn get_status_line(&self) -> &[String] {
85        &self.status_line
86    }
87
88    pub fn get_wildcard(&self) -> Option<&String> {
89        self.wildcard.as_ref()
90    }
91
92    pub fn get_http2(&self) -> bool {
93        self.is_http2
94    }
95
96    pub fn set_http2(mut self, w: bool) -> Self {
97        self.is_http2 = w;
98        self
99    }
100}
101
102impl<'a> From<&'a mut Request> for Wildcard<&'a str> {
103    fn from(value: &'a mut Request) -> Self {
104        Wildcard {
105            wildcard: value.wildcard.as_ref().unwrap(),
106        }
107    }
108}
109
110//impl<'a> From<&'a mut Request> for Wildcard<&'a [u8]> {
111//    fn from(value: &'a mut Request) -> Self {
112//        Wildcard {
113//            wildcard: value.wildcard.as_ref().unwrap().as_bytes(),
114//        }
115//    }
116//}
117
118impl<'a> From<&'a mut Request> for &'a HashMap<String, String> {
119    fn from(value: &'a mut Request) -> Self {
120        value.get_headers()
121    }
122}
123
124impl<'a> From<&'a mut Request> for &'a [u8] {
125    fn from(value: &'a mut Request) -> Self {
126        value.get_raw_body()
127    }
128}
129
130impl<'a> From<&'a mut Request> for Option<&'a str> {
131    fn from(value: &'a mut Request) -> Self {
132        value.get_parsed_body()
133    }
134}
135
136impl From<&mut Request> for Request {
137    fn from(value: &mut Request) -> Self {
138        mem::take(value)
139    }
140}
141use thiserror::Error;
142
143#[derive(Error, Debug)]
144pub enum RequestError {
145    #[error("failed to parse status line")]
146    StatusLineErr,
147    #[error("failed to parse headers")]
148    HeadersErr,
149}