some progress
I honestly forgot what I did
This commit is contained in:
parent
1157c75d2d
commit
b7cd456c5e
153
src/main.rs
153
src/main.rs
@ -4,10 +4,6 @@ use std::{
|
|||||||
net::{TcpListener, TcpStream},
|
net::{TcpListener, TcpStream},
|
||||||
};
|
};
|
||||||
|
|
||||||
const VALID_METHODS: [&str; 8] = [
|
|
||||||
"GET", "HEAD", "POST", "PUT", "DELETE", "CONNECT", "OPTIONS", "TRACE",
|
|
||||||
];
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct StartLine {
|
struct StartLine {
|
||||||
method: String,
|
method: String,
|
||||||
@ -30,31 +26,91 @@ impl StartLine {
|
|||||||
}
|
}
|
||||||
let tmp = method.as_str();
|
let tmp = method.as_str();
|
||||||
|
|
||||||
if VALID_METHODS.contains(&tmp) {
|
if [
|
||||||
|
"GET", "HEAD", "POST", "PUT", "DELETE", "CONNECT", "OPTIONS", "TRACE",
|
||||||
|
]
|
||||||
|
.contains(&tmp)
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: make the checks less shit and actually correct
|
||||||
pub fn is_valid_target(target: &String) -> bool {
|
pub fn is_valid_target(target: &String) -> bool {
|
||||||
if target.trim().is_empty() {
|
if target.trim().is_empty() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// origin-form
|
||||||
|
if target.starts_with("/") {
|
||||||
|
if target.contains("?") && target.split("?").count() != 2 {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// absolute-form
|
||||||
|
if target.starts_with("http://") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// authority-form
|
||||||
|
if target.contains(":") && target.split(":").count() == 2 {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// asterisk-form
|
||||||
|
if target.trim() == "*" {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_valid_version(version: &String) -> bool {
|
pub fn is_valid_version(version: &String) -> bool {
|
||||||
if version.trim().is_empty() {
|
if version.trim().is_empty() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let http_name = version.trim();
|
||||||
|
|
||||||
|
if http_name.starts_with("HTTP/") {
|
||||||
|
let version_numbers = http_name.trim_start_matches("HTTP/");
|
||||||
|
let version_numbers = version_numbers.split(".").collect::<Vec<&str>>();
|
||||||
|
if version_numbers.len() != 2 {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
let major = match version_numbers[0].parse::<u8>() {
|
||||||
|
Ok(val) => val,
|
||||||
|
Err(_) => {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let minor = match version_numbers[2].parse::<u8>() {
|
||||||
|
Ok(val) => val,
|
||||||
|
Err(_) => {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if major <= 9 && minor <= 9 {
|
||||||
return true;
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_start_line(input: String) -> Option<StartLine> {
|
fn parse_start_line(input: String) -> Option<StartLine> {
|
||||||
|
if input.ends_with(" ") {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
let mut start_line = StartLine::new();
|
let mut start_line = StartLine::new();
|
||||||
let vec = input.trim().split(" ").collect::<Vec<&str>>();
|
let vec = input.trim().split(" ").collect::<Vec<&str>>();
|
||||||
|
|
||||||
@ -74,12 +130,55 @@ fn parse_start_line(input: String) -> Option<StartLine> {
|
|||||||
|
|
||||||
let version = String::from(vec[2]);
|
let version = String::from(vec[2]);
|
||||||
if StartLine::is_valid_version(&version) {
|
if StartLine::is_valid_version(&version) {
|
||||||
|
if version.trim() == "HTTP/1.1" || version.trim() == "HTTP/1.0" {
|
||||||
start_line.version = version;
|
start_line.version = version;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Some(start_line);
|
return Some(start_line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_field_lines(reader: &mut BufReader<&mut TcpStream>) -> Option<HashMap<String, String>> {
|
||||||
|
let mut line: String;
|
||||||
|
let mut field_lines: HashMap<String, String> = HashMap::new();
|
||||||
|
let mut is_first_line = true;
|
||||||
|
|
||||||
|
// Read field-lines till I hit an empty line
|
||||||
|
loop {
|
||||||
|
line = String::new();
|
||||||
|
reader.read_line(&mut line).unwrap();
|
||||||
|
|
||||||
|
if line.starts_with(" ") && is_first_line {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !line.ends_with("\r\n") {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
if line.trim().is_empty() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
let field_line = line.split_once(":").expect("Shits fucked: {}");
|
||||||
|
|
||||||
|
// Check if client has send more than one Host line
|
||||||
|
if field_lines.contains_key(&String::from("Host")) && field_line.0 == "Host" {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
field_lines.insert(field_line.0.to_owned(), field_line.1.trim().to_owned());
|
||||||
|
|
||||||
|
is_first_line = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !field_lines.contains_key(&String::from("Host")) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Some(field_lines);
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_request(mut stream: TcpStream) {
|
fn handle_request(mut stream: TcpStream) {
|
||||||
let mut line = String::new();
|
let mut line = String::new();
|
||||||
let mut reader = BufReader::new(&mut stream);
|
let mut reader = BufReader::new(&mut stream);
|
||||||
@ -120,12 +219,11 @@ fn handle_request(mut stream: TcpStream) {
|
|||||||
Some(val) => val,
|
Some(val) => val,
|
||||||
None => {
|
None => {
|
||||||
stream
|
stream
|
||||||
.write_all(b"HTTP/1.1 400 Bad Request\r\n\r\nInvalid start-line")
|
.write_all(b"HTTP/1.1 400 Bad Request\r\n\r\nInvalid Header")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
dbg!(&start_line);
|
dbg!(&start_line);
|
||||||
|
|
||||||
if start_line.method != "GET" {
|
if start_line.method != "GET" {
|
||||||
@ -135,44 +233,21 @@ fn handle_request(mut stream: TcpStream) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut is_first_line = true;
|
let field_lines = match parse_field_lines(&mut reader) {
|
||||||
let mut field_lines: HashMap<String, String> = HashMap::new();
|
Some(val) => val,
|
||||||
|
None => {
|
||||||
loop {
|
|
||||||
let mut line = String::new();
|
|
||||||
reader.read_line(&mut line).unwrap();
|
|
||||||
// print!("{line}");
|
|
||||||
|
|
||||||
if line.starts_with(" ") {
|
|
||||||
if !is_first_line {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
stream
|
stream
|
||||||
.write_all(b"HTTP/1.1 400 Bad Request\r\n\r\nCannot have whitespace between the start-line and field-lines")
|
.write_all(b"HTTP/1.1 400 Bad Request\r\n\r\nInvalid Header")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
// I will not support ignoring the CR
|
|
||||||
if !line.ends_with("\r\n") {
|
|
||||||
stream
|
|
||||||
.write_all(b"HTTP/1.1 400 Bad Request\r\n\r\nLines must end with CRLF")
|
|
||||||
.unwrap();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if line.trim().is_empty() {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
let field_line = line.split_once(":").expect("Shits fucked: {}");
|
|
||||||
field_lines.insert(field_line.0.to_owned(), field_line.1.trim().to_owned());
|
|
||||||
|
|
||||||
is_first_line = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
dbg!(&field_lines);
|
dbg!(&field_lines);
|
||||||
|
|
||||||
|
// let mut body: Vec<u8> = vec![];
|
||||||
|
// reader.read_to_end(&mut body).unwrap();
|
||||||
|
// dbg!(&body);
|
||||||
|
|
||||||
stream
|
stream
|
||||||
.write_all(b"HTTP/1.1 200 OK\r\n\r\nHello, World!\r\n")
|
.write_all(b"HTTP/1.1 200 OK\r\n\r\nHello, World!\r\n")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user