use super::{
all_headers,
array_to_vec,
http,
http_version,
read_body,
http_method,
to_space
};
use crate::combinators::{
crlf,
slash,
spaces
};
use http::{Request, Version};
use std::io::Read;
use std::net::TcpStream;
use std::str;
#[derive(PartialEq, Debug)]
struct RequestLine<'a> {
method: &'a str,
target: &'a str, version: &'a str,
}
named!( read_request_line <RequestLine>,
do_parse!(
method: http_method >> opt!(spaces) >> target: to_space >> opt!(spaces) >>
http >> slash >> version: http_version >> crlf >>
(RequestLine {method: method, target: target , version: version})
)
);
fn _read_http_request(mut stream: TcpStream) -> Result<Request<Vec<u8>>, http::Error> {
let mut buf = [0; 1024];
stream.read(&mut buf).unwrap();
let msg = str::from_utf8(&buf).unwrap();
let (rest1, req_line) = read_request_line(msg.as_bytes()).unwrap();
let (rest2, headers) = all_headers(rest1).unwrap();
let mut request = Request::builder()
.method(req_line.method)
.uri(req_line.target);
request = match req_line.version {
"0.9" => request.version( Version::HTTP_09 ),
"1.0" => request.version( Version::HTTP_10 ),
"1.1" => request.version( Version::HTTP_11 ),
"2.0" => request.version( Version::HTTP_2 ),
"3.0" => request.version( Version::HTTP_3 ),
_ => { request } };
let mut content_length = 0;
for elem in headers.iter() {
if elem.key.to_lowercase() == "content-length" {
content_length = elem.value.parse::<usize>().unwrap();
}
request = request.header(elem.key, elem.value);
}
if rest2.len() < content_length {
let mut buf2 = vec![0; content_length - rest2.len()];
stream.read(&mut buf2).unwrap();
let mut body_vec: Vec<u8> = array_to_vec(rest2);
for i in buf2.iter() {
body_vec.push(*i);
}
return request.body(body_vec);
} else {
let (_, body) = read_body(rest2).unwrap();
let body_vec: Vec<u8> = array_to_vec(body);
return request.body(body_vec);
}
}
pub fn read_http_request(stream: TcpStream) -> Result<Request<Vec<u8>>, http::Error> {
_read_http_request(stream)
}