silver_rs/
request.rs

1use std::{fmt, io, slice, str};
2
3use bytes::BytesMut;
4
5use httparse;
6
7pub struct Request {
8    method: Slice,
9    path: Slice,
10    version: u8,
11    headers: Vec<(Slice, Slice)>,
12    data: BytesMut,
13}
14
15type Slice = (usize, usize);
16
17pub struct RequestHeaders<'req> {
18    headers: slice::Iter<'req, (Slice, Slice)>,
19    req: &'req Request,
20}
21
22impl Request {
23    pub fn method(&self) -> &str {
24        str::from_utf8(self.slice(&self.method)).unwrap()
25    }
26
27    pub fn path(&self) -> &str {
28        str::from_utf8(self.slice(&self.path)).unwrap()
29    }
30
31    pub fn version(&self) -> u8 {
32        self.version
33    }
34
35    pub fn headers(&self) -> RequestHeaders {
36        RequestHeaders {
37            headers: self.headers.iter(),
38            req: self,
39        }
40    }
41
42    fn slice(&self, slice: &Slice) -> &[u8] {
43        &self.data[slice.0..slice.1]
44    }
45}
46
47impl fmt::Debug for Request {
48    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
49        write!(f, "<HTTP Request {} {}>", self.method(), self.path())
50    }
51}
52
53pub fn decode(buf: &mut BytesMut) -> io::Result<Option<Request>> {
54    let (method, path, version, headers, amt) = {
55        let mut headers = [httparse::EMPTY_HEADER; 16];
56        let mut r = httparse::Request::new(&mut headers);
57        let status = try!(r.parse(buf).map_err(|e| {
58            let msg = format!("failed to parse http request: {:?}", e);
59            io::Error::new(io::ErrorKind::Other, msg)
60        }));
61
62        let amt = match status {
63            httparse::Status::Complete(amt) => amt,
64            httparse::Status::Partial => return Ok(None),
65        };
66
67        let toslice = |a: &[u8]| {
68            let start = a.as_ptr() as usize - buf.as_ptr() as usize;
69            assert!(start < buf.len());
70            (start, start + a.len())
71        };
72
73        (
74            toslice(r.method.unwrap().as_bytes()),
75            toslice(r.path.unwrap().as_bytes()),
76            r.version.unwrap(),
77            r.headers
78                .iter()
79                .map(|h| (toslice(h.name.as_bytes()), toslice(h.value)))
80                .collect(),
81            amt,
82        )
83    };
84
85    Ok(Request {
86        method: method,
87        path: path,
88        version: version,
89        headers: headers,
90        data: buf.split_to(amt),
91    }
92    .into())
93}
94
95impl<'req> Iterator for RequestHeaders<'req> {
96    type Item = (&'req str, &'req [u8]);
97
98    fn next(&mut self) -> Option<(&'req str, &'req [u8])> {
99        self.headers.next().map(|&(ref a, ref b)| {
100            let a = self.req.slice(a);
101            let b = self.req.slice(b);
102            (str::from_utf8(a).unwrap(), b)
103        })
104    }
105}