http_tiny/
header.rs

1use crate::{
2    error::Result,
3    helpers::{
4        self, BufReadExt, SliceU8Ext,
5        MatchConfig::{ Required, Trim }
6    }
7};
8use std::{
9    collections::BTreeMap, iter::FromIterator, ops::Deref,
10    io::{ BufRead, Write }
11};
12
13
14/// A HTTP header
15#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
16pub struct Header {
17    /// The start line
18    start_line: HeaderStartLine,
19    /// The header fields
20    fields: HeaderFields
21}
22impl Header {
23    /// Creates a new HTTP/1.1 header
24    pub const fn new(start_line: HeaderStartLine, fields: HeaderFields) -> Self {
25        Self { start_line, fields }
26    }
27
28    /// The start line
29    pub fn start_line(&self) -> &HeaderStartLine {
30        &self.start_line
31    }
32    /// The start line
33    pub fn start_line_mut(&mut self) -> &mut HeaderStartLine {
34        &mut self.start_line
35    }
36
37    /// The header fields
38    pub fn fields(&self) -> &HeaderFields {
39        &self.fields
40    }
41    /// The header fields
42    pub fn fields_mut(&mut self) -> &mut HeaderFields {
43        &mut self.fields
44    }
45    
46    /// Loads a HTTP header from `bytes` and returns the remaining bytes
47    ///
48    /// # Warning:
49    /// This function will read forever until there is either a `\r\n\r\n` or an EOF. To prevent DOS-attacks, it is
50    /// strongly recommended to wrap the `source` into an [`IoLimiter<T>`](crate::IoLimiter) to limit the amount of data
51    /// that will be read.
52    pub fn read<T>(source: &mut T) -> Result<Self> where T: BufRead {
53        // Read the entire header
54        let header = source.read_word("\r\n\r\n", [Required])?;
55        let mut header = helpers::memreader(header);
56
57        // Read start line and fields
58        let start_line = HeaderStartLine::read(&mut header)?;
59        let fields = HeaderFields::read(&mut header)?;
60        Ok(Self { start_line, fields })
61    }
62    /// Writes the HTTP header
63    pub fn write_all(&self, output: &mut dyn Write) -> Result {
64        self.start_line.write_all(output)?;
65        self.fields.write_all(output)?;
66        output.flush()?;
67        Ok(())
68    }
69}
70
71
72/// The start line
73#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
74pub struct HeaderStartLine {
75    field0: Vec<u8>,
76    field1: Vec<u8>,
77    field2: Vec<u8>,
78}
79impl HeaderStartLine {
80    /// Creates a new HTTP/1.1 request
81    pub fn new_request<T, U>(method: T, target: U) -> Self where T: Into<Vec<u8>>, U: Into<Vec<u8>> {
82        Self {
83            field0: method.into(),
84            field1: target.into(),
85            field2: "HTTP/1.1".into()
86        }
87    }
88    /// Creates a new HTTP/1.1 response
89    pub fn new_response<T>(status: u16, reason: T) -> Self where T: Into<Vec<u8>> {
90        Self {
91            field0: "HTTP/1.1".into(),
92            field1: status.to_string().into(),
93            field2: reason.into()
94        }
95    }
96
97    /// Interprets the start line as request and returns the field containing the request method
98    pub fn request_method(&self) -> &[u8] {
99        &self.field0
100    }
101    /// Interprets the start line as request and returns the field containing the request method
102    pub fn request_method_mut(&mut self) -> &mut Vec<u8> {
103        &mut self.field0
104    }
105    /// Interprets the start line as request and returns the field containing the request target
106    pub fn request_target(&self) -> &[u8] {
107        &self.field1
108    }
109    /// Interprets the start line as request and returns the field containing the request target
110    pub fn request_target_mut(&mut self) -> &mut Vec<u8> {
111        &mut self.field1
112    }
113
114    /// Interprets the start line as response and returns the field containing the response status code
115    pub fn response_binstatus(&self) -> &[u8] {
116        &self.field1
117    }
118    /// Interprets the start line as response and returns the field containing the response status code
119    pub fn response_binstatus_mut(&mut self) -> &mut Vec<u8> {
120        &mut self.field1
121    }
122    /// Interprets the start line as response and returns the field containing the response status code
123    pub fn response_reason(&self) -> &[u8] {
124        &self.field2
125    }
126    pub fn response_reason_mut(&mut self) -> &mut Vec<u8> {
127        &mut self.field2
128    }
129
130    /// Reads the start line from `source`
131    pub fn read<T>(source: &mut T) -> Result<Self> where T: BufRead {
132        // Read the start line
133        let line = source.read_word("\r\n", [Required, Trim])?;
134        let mut line = helpers::memreader(line);
135        let this = Self {
136            field0: line.read_word(" ", [Required, Trim])?,
137            field1: line.read_word(" ", [Required, Trim])?,
138            field2: line.read_all([Required])?
139        };
140        Ok(this)
141    }
142    /// Writes the HTTP start line
143    pub fn write_all(&self, output: &mut dyn Write) -> Result {
144        output.write_all(&self.field0)?;
145        output.write_all(b" ")?;
146        output.write_all(&self.field1)?;
147        output.write_all(b" ")?;
148        output.write_all(&self.field2)?;
149        output.write_all(b"\r\n")?;
150        Ok(())
151    }
152}
153
154
155/// Some header fields
156#[derive(Debug, Default, Clone, Eq, PartialEq, Ord, PartialOrd)]
157pub struct HeaderFields {
158    /// The header fields
159    fields: BTreeMap<Vec<u8>, Vec<u8>>
160}
161impl HeaderFields {
162    /// Creates a new header field map
163    pub fn new() -> Self {
164        Self { fields: BTreeMap::new() }
165    }
166
167    /// Gets the value for the field with the given name
168    pub fn get<T>(&self, name: T) -> Option<&[u8]> where T: AsRef<[u8]> {
169        let name = name.as_ascii_lowercase();
170        self.fields.get(name.as_ref()).map(|s| s.as_ref())
171    }
172    /// Sets the value for a fiels with the given name
173    pub fn set<A, B>(&mut self, name: A, value: B) where A: AsRef<[u8]>, B: Into<Vec<u8>> {
174        let name = name.as_ascii_lowercase();
175        self.fields.insert(name.into(), value.into());
176    }
177
178    /// Reads the header fields from `source`
179    pub fn read<T>(source: &mut T) -> Result<Self> where T: BufRead {
180        let mut this = HeaderFields::new();
181        'read_lines: loop {
182            // Unwrap the next line and check for end of header
183            let mut line = match source.read_word("\r\n", [Required, Trim])? {
184                line if line.is_empty() => break 'read_lines,
185                line => helpers::memreader(line)
186            };
187            let key = line.read_word(":", [Required, Trim])?;
188            let value = line.read_all([Required])?;
189            
190            // Trim the leading spaces and insert the header pair
191            let leading_whitespace = value.iter().take_while(|b| **b == b' ').count();
192            let value = &value[leading_whitespace..];
193            this.set(key, value);
194        }
195
196        Ok(this)
197    }
198    /// Writes the HTTP header fields
199    pub fn write_all(&self, output: &mut dyn Write) -> Result {
200        for (key, value) in self.fields.iter() {
201            output.write_all(key)?;
202            output.write_all(b": ")?;
203            output.write_all(value)?;
204            output.write_all(b"\r\n")?;
205        }
206        output.write_all(b"\r\n")?;
207        Ok(())
208    }
209}
210impl Deref for HeaderFields {
211    type Target = BTreeMap<Vec<u8>, Vec<u8>>;
212
213    fn deref(&self) -> &Self::Target {
214        &self.fields
215    }
216}
217impl<K, V> FromIterator<(K, V)> for HeaderFields where K: Into<Vec<u8>>, V: Into<Vec<u8>> {
218    fn from_iter<T: IntoIterator<Item = (K, V)>>(pairs: T) -> Self {
219        let fields = pairs.into_iter()
220            .map(|(k, v)| (k.into(), v.into()))
221            .map(|(k, v)| (k.to_ascii_lowercase(), v))
222            .collect();
223        Self { fields }
224    }
225}
226impl IntoIterator for HeaderFields {
227    type Item = <BTreeMap<Vec<u8>, Vec<u8>> as IntoIterator>::Item;
228    type IntoIter = <BTreeMap<Vec<u8>, Vec<u8>> as IntoIterator>::IntoIter;
229
230    fn into_iter(self) -> Self::IntoIter {
231        self.fields.into_iter()
232    }
233}