making some horrifyingly cursed progress
This commit is contained in:
parent
426e70e840
commit
d917646b74
148
src/main.rs
148
src/main.rs
@ -1,27 +1,141 @@
|
|||||||
use std::{
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
io::{BufRead, BufReader, Write},
|
io::{BufRead, BufReader, Write},
|
||||||
net::TcpListener,
|
net::{TcpListener, TcpStream},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const VALID_METHODS: [&str; 8] = [
|
||||||
|
"GET", "HEAD", "POST", "PUT", "DELETE", "CONNECT", "OPTIONS", "TRACE",
|
||||||
|
];
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct StartLine {
|
||||||
|
method: String,
|
||||||
|
target: String,
|
||||||
|
version: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StartLine {
|
||||||
|
pub fn new(input: String) -> Self {
|
||||||
|
let input_array = input.trim().split(" ").collect::<Vec<&str>>();
|
||||||
|
|
||||||
|
Self {
|
||||||
|
method: input_array[0].to_owned(),
|
||||||
|
target: input_array[1].to_owned(),
|
||||||
|
version: input_array[2].to_owned(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_valid_method(input: &StartLine) -> bool {
|
||||||
|
if input.method.is_empty() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
let method: &str = input.method.as_str();
|
||||||
|
|
||||||
|
if VALID_METHODS.contains(&method) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_request(mut stream: TcpStream) {
|
||||||
|
let mut reader = BufReader::new(&mut stream);
|
||||||
|
|
||||||
|
let mut start_line = String::new();
|
||||||
|
reader.read_line(&mut start_line).unwrap();
|
||||||
|
|
||||||
|
// I will not support ignoring the CR
|
||||||
|
if !start_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Request can have one or many empty lines preceding the request-line and I will ignore these
|
||||||
|
loop {
|
||||||
|
if !start_line.trim().is_empty() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
reader.read_line(&mut start_line).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
if start_line.trim().is_empty() {
|
||||||
|
reader.read_line(&mut start_line).unwrap();
|
||||||
|
}
|
||||||
|
if start_line.trim().is_empty() {
|
||||||
|
stream
|
||||||
|
.write_all(b"HTTP/1.1 400 Bad Request\r\n\r\nReceived too many preceding empty lines")
|
||||||
|
.unwrap();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let start_line = StartLine::new(start_line);
|
||||||
|
dbg!(&start_line);
|
||||||
|
|
||||||
|
if !StartLine::is_valid_method(&start_line) {
|
||||||
|
stream
|
||||||
|
.write_all(b"HTTP/1.1 400 Bad Request\r\n\r\nInvalid request method")
|
||||||
|
.unwrap();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if start_line.method != "GET" {
|
||||||
|
stream
|
||||||
|
.write_all(b"HTTP/1.1 501 Not Implemented\r\n\r\nServer currently only supports GET")
|
||||||
|
.unwrap();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut is_first_line = true;
|
||||||
|
let mut field_lines: HashMap<String, String> = HashMap::new();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let mut line = String::new();
|
||||||
|
reader.read_line(&mut line).unwrap();
|
||||||
|
print!("{line}");
|
||||||
|
|
||||||
|
if line.starts_with(" ") {
|
||||||
|
if !is_first_line {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
stream
|
||||||
|
.write_all(b"HTTP/1.1 400 Bad Request\r\n\r\nCannot have whitespace between the start-line and field-lines")
|
||||||
|
.unwrap();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
stream
|
||||||
|
.write_all(b"HTTP/1.1 200 OK\r\n\r\nHello, World!")
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let listener = TcpListener::bind("127.0.0.1:8080").unwrap();
|
let listener = TcpListener::bind("127.0.0.1:8080").unwrap();
|
||||||
|
|
||||||
for stream in listener.incoming() {
|
for stream in listener.incoming() {
|
||||||
let mut stream = stream.unwrap();
|
let stream = stream.unwrap();
|
||||||
let mut reader = BufReader::new(&mut stream);
|
handle_request(stream)
|
||||||
|
|
||||||
loop {
|
|
||||||
let mut line = String::new();
|
|
||||||
reader.read_line(&mut line).unwrap();
|
|
||||||
print!("{line}");
|
|
||||||
|
|
||||||
if line.trim().is_empty() {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stream
|
|
||||||
.write_all(b"HTTP/1.1 200 OK\r\n\r\nHello, World!")
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user