tinyhttp_internal/
request.rs

1use std::{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: HeaderMap,
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: HeaderMap,
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        std::str::from_utf8(&self.body).ok()
69    }
70
71    /// Get request headers in a HashMap
72    pub fn get_headers(&self) -> &HeaderMap {
73        #[cfg(feature = "log")]
74        log::trace!("Headers: {:#?}", self.raw_headers);
75
76        &self.raw_headers
77    }
78
79    /// Get status line of request
80    pub fn get_status_line(&self) -> &[String] {
81        &self.status_line
82    }
83
84    pub fn get_wildcard(&self) -> Option<&String> {
85        self.wildcard.as_ref()
86    }
87
88    pub fn get_http2(&self) -> bool {
89        self.is_http2
90    }
91
92    #[allow(dead_code)]
93    pub(crate) fn set_http2(mut self, w: bool) -> Self {
94        self.is_http2 = w;
95        self
96    }
97}
98
99impl<'a> From<&'a mut Request> for Wildcard<&'a str> {
100    fn from(value: &'a mut Request) -> Self {
101        Wildcard {
102            wildcard: value.wildcard.as_ref().unwrap(),
103        }
104    }
105}
106
107//impl<'a> From<&'a mut Request> for Wildcard<&'a [u8]> {
108//    fn from(value: &'a mut Request) -> Self {
109//        Wildcard {
110//            wildcard: value.wildcard.as_ref().unwrap().as_bytes(),
111//        }
112//    }
113//}
114
115// TODO: Add docs here
116impl<'a> From<&'a mut Request> for &'a HeaderMap {
117    fn from(value: &'a mut Request) -> Self {
118        value.get_headers()
119    }
120}
121
122impl<'a> From<&'a mut Request> for &'a [u8] {
123    fn from(value: &'a mut Request) -> Self {
124        value.get_raw_body()
125    }
126}
127
128impl<'a> From<&'a mut Request> for Option<&'a str> {
129    fn from(value: &'a mut Request) -> Self {
130        value.get_parsed_body()
131    }
132}
133
134impl From<&mut Request> for Request {
135    fn from(value: &mut Request) -> Self {
136        mem::take(value)
137    }
138}
139use thiserror::Error;
140
141use crate::headers::HeaderMap;
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}