1use std::{io, str, fmt};
2use std::collections::HashMap;
3use serde;
4use bytes::BytesMut;
5use serde_json;
6use smallvec::SmallVec;
7
8use httparse;
9use crate::httplib;
10
11
12pub trait RequestWithParams {
13 fn set_params(&mut self, _: HashMap<String, String>);
14}
15
16#[derive(Default)]
22pub struct Request {
23 body: Slice,
24 method: Slice,
25 path: Slice,
26 version: u8,
27 pub headers: SmallVec<[(Slice, Slice); 8]>,
28 data: BytesMut,
29 pub params: HashMap<String, String>
30}
31
32type Slice = (usize, usize);
33
34impl Request {
35 pub fn new() -> Self {
39 Request {
40 body: (0,0),
41 method: (0,0),
42 path: (0,0),
43 version: 0,
44 headers: SmallVec::new(),
45 data: BytesMut::new(),
46 params: HashMap::new(),
47 }
48 }
49
50 pub fn raw_body(&self) -> &[u8] {
54 self.slice(&self.body)
55 }
56
57 pub fn body(&self) -> &str {
61 str::from_utf8(self.slice(&self.body)).unwrap()
62 }
63
64 pub fn method(&self) -> &str {
68 str::from_utf8(self.slice(&self.method)).unwrap()
69 }
70
71 pub fn path(&self) -> &str {
75 str::from_utf8(self.slice(&self.path)).unwrap()
76 }
77
78 pub fn version(&self) -> u8 {
82 self.version
83 }
84
85 pub fn headers(&self) -> HashMap<String, String> {
90 let mut header_map = HashMap::new();
91
92 for slice_pair in self.headers.iter() {
93 header_map.insert(
94 str::from_utf8(self.slice(&slice_pair.0)).unwrap().to_owned().to_lowercase(),
95 str::from_utf8(self.slice(&slice_pair.1)).unwrap().to_owned()
96 );
97 }
98
99 header_map
100 }
101
102 pub fn body_as<'a, T>(&self, body: &'a str) -> serde_json::Result<T>
106 where T: serde::de::Deserialize<'a>
107 {
108 serde_json::from_str(body)
109 }
110
111 fn slice(&self, slice: &Slice) -> &[u8] {
115 &self.data[slice.0..slice.1]
116 }
117
118 pub fn params(&self) -> &HashMap<String, String> {
123 &self.params
124 }
125}
126
127impl RequestWithParams for Request {
128 fn set_params(&mut self, params: HashMap<String, String>) {
129 self.params = params;
130 }
131}
132
133impl fmt::Debug for Request {
134 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
135 write!(f, "<HTTP Request {} {}>", self.method(), self.path())
136 }
137}
138
139
140pub fn decode(buf: &mut BytesMut) -> io::Result<Option<Request>> {
141 let (method, path, version, headers, amt, body_len) = {
144 let mut headers = [httparse::EMPTY_HEADER; 32];
145 let mut r = httparse::Request::new(&mut headers);
146 let mut body_len: usize = 0;
147 let mut header_vec = SmallVec::new();
148 let status = r.parse(buf).map_err(|e| {
149 let msg = format!("failed to parse http request: {:?}", e);
150 eprintln!("msg: {}", msg);
151 io::Error::new(io::ErrorKind::Other, msg)
152 })?;
153 let amt = match status {
154 httparse::Status::Complete(amt) => amt,
155 httparse::Status::Partial => {
156 return Ok(None)
157 },
158 };
159 let toslice = |a: &[u8]| {
160 let start = a.as_ptr() as usize - buf.as_ptr() as usize;
161 assert!(start < buf.len());
162 (start, start + a.len())
163 };
164 for header in r.headers.iter() {
165 let header_name = httplib::header::CONTENT_LENGTH;
166
167 if header.name == header_name {
168 let value = str::from_utf8(header.value).unwrap_or("0");
169 body_len = value.parse::<usize>().unwrap_or(0);
170 }
171
172 header_vec.push((toslice(header.name.as_bytes()), toslice(header.value)));
173 }
174
175 (toslice(r.method.unwrap().as_bytes()),
176 toslice(r.path.unwrap().as_bytes()),
177 r.version.unwrap(),
178 header_vec,
179 amt,
180 body_len)
181 };
182
183 if amt + body_len != buf.len() {
184 Ok(None)
185 } else {
186 Ok(Request {
187 method,
188 path,
189 version,
190 headers,
191 data: buf.split_to(amt + body_len),
192 body: (amt, amt + body_len),
193 params: HashMap::new()
194 }.into())
195 }
196}