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