91 lines
2.7 KiB
Rust
91 lines
2.7 KiB
Rust
use crate::*;
|
|
use log::info;
|
|
use std::collections::HashMap;
|
|
use std::net::SocketAddr;
|
|
use wetstring::{RequestParseResult, RequestParser};
|
|
|
|
pub struct HttpRequestParser {
|
|
bytes: Vec<u8>,
|
|
client_address: SocketAddr,
|
|
headers: HashMap<String, String>,
|
|
body: Option<Vec<u8>>,
|
|
}
|
|
|
|
impl RequestParser for HttpRequestParser {
|
|
type Req = HttpRequest;
|
|
type Res = HttpResponse;
|
|
|
|
fn new(client_address: SocketAddr) -> Self {
|
|
Self {
|
|
bytes: Vec::new(),
|
|
client_address,
|
|
headers: HashMap::new(),
|
|
body: None,
|
|
}
|
|
}
|
|
|
|
fn push_bytes(&mut self, bytes: &[u8]) {
|
|
self.bytes.extend(bytes);
|
|
}
|
|
fn try_parse(&mut self) -> RequestParseResult<HttpRequest, HttpResponse> {
|
|
let client_error = HttpResponse::client_error();
|
|
if self.bytes.len() > 8096 {
|
|
return RequestParseResult::Invalid(client_error);
|
|
}
|
|
|
|
let string = match String::from_utf8(self.bytes.clone()) {
|
|
Ok(string) => string,
|
|
Err(_) => return RequestParseResult::Incomplete,
|
|
};
|
|
let mut lines = string.lines();
|
|
|
|
// Parse request start line
|
|
let (method, target) = match lines.next() {
|
|
Some(line) => match parse_start_line(line) {
|
|
Ok(v) => v,
|
|
Err(e) => {
|
|
info!("{}", e.description());
|
|
return RequestParseResult::Invalid(client_error);
|
|
}
|
|
},
|
|
None => {
|
|
info!("Missing start line from request");
|
|
return RequestParseResult::Invalid(client_error);
|
|
}
|
|
};
|
|
|
|
// Parse request headers
|
|
// for line in lines {
|
|
// if line == "" {
|
|
// break;
|
|
// };
|
|
// match parse_header_line(line) {
|
|
// Ok((key, value)) => self.headers.insert(key, value),
|
|
// Err(_) => return RequestParseResult::Invalid(client_error),
|
|
// };
|
|
// }
|
|
|
|
let request = HttpRequest {
|
|
client_address: self.client_address,
|
|
method,
|
|
target,
|
|
headers: std::mem::take(&mut self.headers),
|
|
body: std::mem::take(&mut self.body),
|
|
};
|
|
|
|
RequestParseResult::Complete(request)
|
|
}
|
|
}
|
|
|
|
fn parse_start_line(line: &str) -> Result<(Method, RequestTarget), RequestError> {
|
|
let mut split = line.split_whitespace();
|
|
|
|
let method_str = split.next().ok_or(RequestError::StartLineMissingMethod)?;
|
|
let target_str = split.next().ok_or(RequestError::StartLineMissingTarget)?;
|
|
|
|
let method = Method::parse(method_str)?;
|
|
let target = RequestTarget::parse(target_str)?;
|
|
|
|
Ok((method, target))
|
|
}
|