diff options
| -rw-r--r-- | src/main.rs | 107 |
1 files changed, 78 insertions, 29 deletions
diff --git a/src/main.rs b/src/main.rs index bbae91e..0ea01c5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,10 @@ use std::collections::HashMap; +use std::fmt::format; use std::io::{Read, Write}; use std::net::{TcpListener, TcpStream}; use std::str; -use itertools::Itertools; +use itertools::{join, Itertools}; enum StatusCode { // 2xx Success @@ -20,11 +21,14 @@ enum StatusCode { NotFound, } +type Endpoint = String; +type Target = String; + #[derive(Debug)] enum HTTPMethod { - Get(String), - Post(String), - Put(String), + Get((Endpoint, Target)), + Post((Endpoint, Target)), + Put((Endpoint, Target)), } impl From<StatusCode> for String { @@ -42,9 +46,9 @@ impl From<HTTPMethod> for String { fn from(val: HTTPMethod) -> Self { use HTTPMethod::*; match val { - Get(target) => "GET".to_string() + &target, - Post(target) => "POST".to_string() + &target, - Put(target) => "PUT".to_string() + &target, + Get((endpoint, target)) => "GET".to_string() + &endpoint + &target, + Post((endpoint, target)) => "POST".to_string() + &endpoint + &target, + Put((endpoint, target)) => "PUT".to_string() + &endpoint + &target, } } } @@ -67,10 +71,12 @@ impl From<&str> for HTTPMethod { fn from(val: &str) -> Self { use HTTPMethod::*; let request_line = val.split(' ').collect_vec(); - let (method, target) = (request_line[0], request_line[1]); + let (method, info) = (request_line[0], request_line[1]); + let info = info.chars().skip(1).collect::<String>() + &"/"; + let (endpoint, target) = info.split_once("/").expect("Should be splitable by /"); match method { - "GET" => Get(target.to_string()), - "POST" => Post(target.to_string()), + "GET" => Get((endpoint.to_string(), target.to_string())), + "POST" => Post((endpoint.to_string(), target.to_string())), _ => { eprintln!("{method} Not Supported Yet"); unreachable!() @@ -124,13 +130,20 @@ impl From<&str> for Request { struct Response { version: String, status: StatusCode, + headers: Option<Headers>, body: Option<String>, } impl Response { - fn new(version: String, status: StatusCode, body: Option<String>) -> Self { + fn new( + version: String, + status: StatusCode, + headers: Option<Headers>, + body: Option<String>, + ) -> Self { Response { version, + headers, status, body, } @@ -139,12 +152,16 @@ impl Response { impl Into<String> for Response { fn into(self) -> String { - format!( - "HTTP/{} {}\r\n{}\r\n", - self.version, - String::from(self.status), - self.body.unwrap_or("".to_string()) - ) + let status_line = format!("HTTP/{} {}", self.version, String::from(self.status)); + let headers = self + .headers + .unwrap_or(Headers(HashMap::new())) + .0 + .iter() + .map(|(key, value)| format!("{key}: {value}\r\n")) + .collect::<String>(); + let body = self.body.unwrap_or("".to_string()); + format!("{status_line}\r\n{headers}\r\n{body}") } } @@ -160,24 +177,56 @@ fn handle_client(mut stream: TcpStream) { println!("Received request: {}", request); let request = Request::from(request); println!("Request after parsing: {:?}", request); - let succses: String = Response::new("1.1".to_string(), StatusCode::Ok, None).into(); + let succses: String = + Response::new("1.1".to_string(), StatusCode::Ok, None, None).into(); let succses = succses.as_bytes(); let not_found: String = - Response::new("1.1".to_string(), StatusCode::NotFound, None).into(); + Response::new("1.1".to_string(), StatusCode::NotFound, None, None).into(); let not_found = not_found.as_bytes(); match request.method { - HTTPMethod::Get(target) => match target.as_str() { - "/" => match stream.write(succses) { - Ok(_) => println!("Response sent successfully"), - Err(e) => eprintln!("Failed to send response: {}", e), - }, - _ => match stream.write(not_found) { - Ok(_) => println!("Response sent successfully"), - Err(e) => eprintln!("Failed to send response: {}", e), - }, - }, + HTTPMethod::Get((endpoint, target)) => { + match (endpoint.as_str(), target.as_str()) { + ("", "") => match stream.write(succses) { + Ok(_) => { + println!("Response sent successfully"); + } + Err(e) => eprintln!("Failed to send response: {}", e), + }, + ("echo", target) => { + let mut headers = HashMap::new(); + headers + .insert("Content-Type".to_string(), "text/plain".to_string()); + headers.insert( + "Content-Length".to_string(), + (target.len() - 1).to_string(), + ); + let body = target[0..target.len() - 1].to_string(); + let response: String = Response::new( + "1.1".to_string(), + StatusCode::Ok, + Some(Headers(headers)), + Some(body), + ) + .into(); + dbg!(&response); + let response = response.as_bytes(); + + match stream.write(response) { + Ok(_) => { + println!("Response sent successfully"); + println!("Hello echo"); + } + Err(e) => eprintln!("Failed to send response: {}", e), + } + } + _ => match stream.write(not_found) { + Ok(_) => println!("Response sent successfully"), + Err(e) => eprintln!("Failed to send response: {}", e), + }, + } + } HTTPMethod::Post(target) => todo!(), HTTPMethod::Put(target) => todo!(), } |
