use crate::enums::http_error::{HttpError, HttpErrorKind};
use crate::enums::http_request_method::HttpRequestMethod;
use crate::enums::http_version::HttpVersion;
use crate::structures::http_message::HttpMessage;
use std::str::FromStr;
pub struct HttpRequest {
pub message: HttpMessage,
pub method: HttpRequestMethod,
pub path: String,
pub version: HttpVersion,
}
impl HttpRequest {
pub fn new(message: HttpMessage) -> Result<Self, HttpError> {
let (method, path, version) = {
let start_line = &message.start_line;
let mut parts = start_line.split_whitespace();
let method_str = parts.next().ok_or(HttpErrorKind::Parse)?;
let path = parts.next().ok_or(HttpErrorKind::Parse)?;
let version_str = parts.next().ok_or(HttpErrorKind::Parse)?;
let method = HttpRequestMethod::from_str(method_str)?;
let version = HttpVersion::from_str(version_str)?;
(method, path.to_string(), version)
};
Ok(HttpRequest {
message,
method,
path,
version,
})
}
}
impl std::ops::Deref for HttpRequest {
type Target = HttpMessage;
fn deref(&self) -> &Self::Target {
&self.message
}
}
impl std::ops::DerefMut for HttpRequest {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.message
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::enums::http_body::HttpBody;
use crate::structures::header::header_list::HttpHeaderList;
#[test]
fn test_valid_request_parsing() {
let start_line = "GET /index.html HTTP/1.1";
let message = HttpMessage::new(start_line, HttpHeaderList::default(), HttpBody::None);
let request = HttpRequest::new(message).unwrap();
assert!(matches!(request.method, HttpRequestMethod::Get));
assert_eq!(request.path, "/index.html");
assert!(matches!(request.version, HttpVersion::Http11));
}
#[test]
fn test_invalid_request_line() {
let start_line = "INVALID";
let message = HttpMessage::new(start_line, HttpHeaderList::default(), HttpBody::None);
let result = HttpRequest::new(message);
assert!(result.is_err());
}
#[test]
fn test_deref() {
let start_line = "GET / HTTP/1.1";
let message = HttpMessage::new(start_line, HttpHeaderList::default(), HttpBody::None);
let request = HttpRequest::new(message).unwrap();
assert_eq!(request.start_line, "GET / HTTP/1.1");
}
}