add http start line parsing + version
This commit is contained in:
parent
1fc257d6b6
commit
48da068f31
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,2 +1,4 @@
|
||||
*.swp
|
||||
|
||||
/target
|
||||
/Cargo.lock
|
||||
|
||||
@ -6,3 +6,5 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
lazy_static = "1.4.0"
|
||||
regex = "1"
|
||||
|
||||
21
src/lib.rs
21
src/lib.rs
@ -1,14 +1,11 @@
|
||||
pub fn add(left: usize, right: usize) -> usize {
|
||||
left + right
|
||||
}
|
||||
//! http parses the request according to the HTTP message specifications
|
||||
//! it also includes `HTTPResponse` to build an HTTPResponse
|
||||
//!
|
||||
//! see: https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages
|
||||
//! NOTE: only few parts of the specification has been implemented
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
mod start_line;
|
||||
mod version;
|
||||
|
||||
#[test]
|
||||
fn it_works() {
|
||||
let result = add(2, 2);
|
||||
assert_eq!(result, 4);
|
||||
}
|
||||
}
|
||||
pub use start_line::HTTPStartLine;
|
||||
pub use version::HTTPVersion;
|
||||
|
||||
6
src/request.rs
Normal file
6
src/request.rs
Normal file
@ -0,0 +1,6 @@
|
||||
use std::collections::VecDeque;
|
||||
|
||||
type RequestParts = (String, VecDeque<String>, String);
|
||||
|
||||
const HTTP_REQUEST_SEPARATOR: &'static str = "\r\n";
|
||||
const NULL_CHAR: &'static str = "\0";
|
||||
91
src/start_line.rs
Normal file
91
src/start_line.rs
Normal file
@ -0,0 +1,91 @@
|
||||
use lazy_static::lazy_static;
|
||||
use regex::Regex;
|
||||
|
||||
use crate::version::HTTPVersion;
|
||||
|
||||
lazy_static! {
|
||||
static ref HTTP_VERSION_REGEX: Regex = Regex::new("^HTTP/(1.1|1.0|2)$").unwrap();
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct HTTPStartLine<'a> {
|
||||
method: &'a str,
|
||||
target: &'a str,
|
||||
version: HTTPVersion,
|
||||
}
|
||||
|
||||
impl<'a> HTTPStartLine<'a> {
|
||||
fn new(method: &'a str, target: &'a str, version: HTTPVersion) -> Self {
|
||||
HTTPStartLine {
|
||||
method: &method,
|
||||
target: &target,
|
||||
version: version,
|
||||
}
|
||||
}
|
||||
|
||||
fn parse(start_line: &'a str) -> Result<Self, &str> {
|
||||
let parts: Vec<&str> = start_line.split(" ").collect();
|
||||
if parts.len() < 3 {
|
||||
return Err("unable to parse the start correctly");
|
||||
}
|
||||
|
||||
let (method, target, version) = (parts[0], parts[1], parts[2]);
|
||||
|
||||
if !Self::check_version(version) {
|
||||
return Err("http version validation failed, unknown version");
|
||||
}
|
||||
|
||||
Ok(HTTPStartLine::new(
|
||||
method,
|
||||
target,
|
||||
HTTPVersion::from(version),
|
||||
))
|
||||
}
|
||||
|
||||
fn check_version(version: &str) -> bool {
|
||||
HTTP_VERSION_REGEX.is_match(version)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_start_line() {
|
||||
struct Expect<'a> {
|
||||
method: &'a str,
|
||||
target: &'a str,
|
||||
version: HTTPVersion,
|
||||
}
|
||||
|
||||
let test_cases: [(&str, Expect, bool); 2] = [
|
||||
(
|
||||
"POST /get/ HTTP/1.1",
|
||||
Expect {
|
||||
method: "POST",
|
||||
target: "/get/",
|
||||
version: HTTPVersion::Http1_1,
|
||||
},
|
||||
true,
|
||||
),
|
||||
(
|
||||
"POST /get/ HTTP/1.1 blablablalfjhskfh",
|
||||
Expect {
|
||||
method: "",
|
||||
target: "",
|
||||
version: HTTPVersion::Unknown,
|
||||
},
|
||||
false,
|
||||
),
|
||||
];
|
||||
|
||||
for (start_line, expect, is_valid) in test_cases {
|
||||
let res = HTTPStartLine::parse(start_line);
|
||||
if is_valid {
|
||||
assert!(res.is_ok());
|
||||
|
||||
let st = res.unwrap();
|
||||
|
||||
assert_eq!(expect.method, st.method);
|
||||
assert_eq!(expect.target, st.target);
|
||||
assert_eq!(expect.target, st.target);
|
||||
}
|
||||
}
|
||||
}
|
||||
29
src/version.rs
Normal file
29
src/version.rs
Normal file
@ -0,0 +1,29 @@
|
||||
#[derive(Debug)]
|
||||
pub enum HTTPVersion {
|
||||
Http1_0,
|
||||
Http1_1,
|
||||
Http2,
|
||||
Unknown,
|
||||
}
|
||||
|
||||
impl Into<String> for HTTPVersion {
|
||||
fn into(self) -> String {
|
||||
match self {
|
||||
Self::Http1_0 => "HTTP/1.0".to_string(),
|
||||
Self::Http1_1 => "HTTP/1.1".to_string(),
|
||||
Self::Http2 => "HTTP/2".to_string(),
|
||||
Self::Unknown => "UNKNOWN".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for HTTPVersion {
|
||||
fn from(http_version: &str) -> Self {
|
||||
match http_version {
|
||||
"HTTP/1.0" => Self::Http1_0,
|
||||
"HTTP/1.1" => Self::Http1_1,
|
||||
"HTTP/2" => Self::Http2,
|
||||
_ => Self::Unknown,
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user