diff --git a/src/main.rs b/src/main.rs index 0fe4519..6294cc5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,12 @@ -use std::{ fmt::Display, io::{BufRead, BufReader, Read, Write}, net::TcpListener }; +#![feature(if_let_guard)] + +use std::{ fmt::Display, io::{ BufRead, BufReader, Write }, net::TcpListener }; use anyhow::Result; use thiserror::Error; +macro_rules! d { () => { Default::default() }; } +macro_rules! f { ($s: expr) => { format!($s) }; } + #[derive(Clone, Debug, Error)] enum E { #[error("Invalid request data found during parsing")] @@ -31,15 +36,15 @@ fn main() -> Result<()> { (method, path, ver) }; - let code = match path.as_str() { - "/" => "200 OK", - _ => "404 Not Found", + let response = match path.as_str() { + "/" => Response::Empty, + p if let Some(echo) = p.strip_prefix("/echo/") => Response::TextPlain(echo), + _ => Response::_404, }; println!("accepted new connection"); - let resp = create_response_simple(code); - let _ = stream.write(&resp); + let _ = stream.write(response.build().as_bytes()); let _ = stream.flush(); } @@ -52,7 +57,33 @@ fn main() -> Result<()> { Ok(()) } - -fn create_response_simple (code: T) -> Vec where T: Display { - format!("HTTP/1.1 {code}\r\n\r\n").into() +#[derive(Debug, Clone)] +enum Response <'a> { + _404, + Empty, + TextPlain (&'a str), +} + + +#[allow(non_upper_case_globals)] +impl Response <'_> { + fn build (self) -> String { + + let (code, body) = match self { + Self::_404 => ("404 Not Found", d!()), + Self::Empty => ("200 OK", d!()), + Self::TextPlain(text) => ("200 OK", text) + }; + + let headers = self.headers().join("\r\n"); + + f!("HTTP/1.1 {code}\r\n{headers}\r\n\r\n{body}").into() + } + + fn headers (&self) -> Vec { + match self { + Self::TextPlain(text) => vec![f!("Content-Type: text/plain"), format!("Content-Length: {}", text.len())], + _ => d!() + } + } }