wetstring_http/src/request_parser.rs

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))
}