diff --git a/src/main.rs b/src/main.rs index 8b9a0dd..b04efc5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -71,12 +71,15 @@ async fn process (mut stream: TcpStream, args: A) -> Result<()> { let headers = Headers::parse(&mut data).await; + let encoding = Encoding::from(headers.get("Accept-Encoding")); + + use Method as M; let response = match (method, target.as_str()) { (M::GET, "/") => Response::Empty, - (M::GET, "/user-agent") => Response::TextPlain(headers.get("User-Agent").to_owned()), + (M::GET, "/user-agent") => Response::TextPlain(headers.get("User-Agent").to_owned(), encoding), // p if let Some(echo) = p.strip_prefix("/echo/") => Response::TextPlain(echo), // a nicer way to do that, not available in stable yet - (M::GET, r) if r.starts_with("/echo/") => Response::TextPlain(r.trim_start_matches("/echo/").to_owned()), + (M::GET, r) if r.starts_with("/echo/") => Response::TextPlain(r.trim_start_matches("/echo/").to_owned(), encoding), (M::GET, r) if r.starts_with("/files/") => 'file : { let Some(path) = &args.directory else { break 'file Response::_500; }; let path = path.join(r.trim_start_matches("/files/")); @@ -136,17 +139,35 @@ impl Headers { } } + #[derive(Debug, Clone)] -enum Response { - _201, - _400, - _404, - _500, - Empty, - TextPlain (String), - OctetStream (Vec) +enum Encoding { + Gzip, + Invalid, + None, } + +impl Encoding { + pub fn header (&self) -> &'static str { + match self { + Self::Gzip => "Content-Encoding: gzip", + _ => d!() + } + } +} + +impl From<&str> for Encoding { + fn from (s: &str) -> Self { + match s.to_ascii_lowercase().as_str() { + "" => Self::None, + "gzip" => Self::Gzip, + _ => Self::Invalid + } + } +} + + #[derive(Debug, Clone, PartialEq, Eq)] enum Method { GET, @@ -172,6 +193,16 @@ impl TryFrom<&str> for Method { } } +#[derive(Debug, Clone)] +enum Response { + _201, + _400, + _404, + _500, + Empty, + TextPlain (String, Encoding), + OctetStream (Vec) +} #[allow(non_upper_case_globals)] impl Response { @@ -186,7 +217,7 @@ impl Response { Self::OctetStream(bytes) => { v.extend_from_slice(&bytes); }, - Self::TextPlain(text) => { + Self::TextPlain(text, _) => { v.extend_from_slice(text.as_bytes()); }, _ => () @@ -207,7 +238,8 @@ impl Response { fn headers (&self) -> Vec { match self { - Self::TextPlain(text) => vec![ + Self::TextPlain(text, enc) => vec![ + enc.header().to_string(), f!("Content-Type: text/plain"), format!("Content-Length: {}", text.len()) ],