From 16511266068dcd821328127459f38eab1387f804 Mon Sep 17 00:00:00 2001 From: "Dawid J. Kubis" Date: Fri, 26 May 2023 19:58:39 +0200 Subject: [PATCH] added favicon, sending binary data in response, ignoring body with non-POST methods, better Response methods (.respond() in particular) --- README.md | 5 +---- src/errors.rs | 2 +- src/http.rs | 42 +++++++++++++++++++++--------------------- src/main.rs | 37 ++++++++++++++++++------------------- src/post.rs | 12 +----------- src/www/favicon.ico | Bin 241886 -> 1253 bytes 6 files changed, 42 insertions(+), 56 deletions(-) diff --git a/README.md b/README.md index e22004d..2f33a8c 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,4 @@ -### TODO: -6. limit storage, maybe with pseudorandomness, find a way to clean old threads -7. better html and css -8. optimize/clean code, improve memory usage +# kchan ### Rules + single page diff --git a/src/errors.rs b/src/errors.rs index 4278819..ce99b57 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -76,6 +76,6 @@ impl From for Response { HandlingError::ServerError(e) => Status::from(e), HandlingError::Io(e) => Status::InternalServerError, }; - Response::new(status, vec![], status.message().to_string()) + Response::new(status, vec![], status.message().into()) } } diff --git a/src/http.rs b/src/http.rs index 6fc526c..4579642 100644 --- a/src/http.rs +++ b/src/http.rs @@ -18,7 +18,7 @@ pub struct Request { pub struct Response { pub status: Status, pub headers: Vec<(String, String)>, - pub body: String, // make into Option> + pub body: Vec, // make into Option> } #[derive(Debug, Clone, Copy)] @@ -31,7 +31,7 @@ pub enum Status { InternalServerError = 500, } -#[derive(Debug)] +#[derive(Debug, PartialEq)] pub enum Method { Get, Post, @@ -114,7 +114,7 @@ impl TryFrom> for Request { } impl Response { - pub fn new(status: Status, headers: Vec<(&str, &str)>, body: String) -> Self { + pub fn new(status: Status, headers: Vec<(&str, &str)>, body: Vec) -> Self { Self { status, headers: headers @@ -124,24 +124,24 @@ impl Response { body, } } -} -impl fmt::Display for Response { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let headers: String = self - .headers - .iter() - .map(|x| format!("{}:{}\n", x.0, x.1)) - .fold(String::from(""), |a, b| format!("{}{}", a, b)); // possibly slow - - write!( - f, - "{} {} {}\n{}\n\n{}", - HTTP_VERSION, - self.status as i32, - self.status.message(), - headers, - self.body, - ) + pub fn respond(&self) -> Vec { + let mut res = vec![]; + res.extend_from_slice(HTTP_VERSION.as_bytes()); + res.extend_from_slice(b" "); + res.extend_from_slice(&(self.status as i32).to_string().as_bytes()); // network endianness + res.extend_from_slice(b" "); + res.extend_from_slice(self.status.message().as_bytes()); + res.extend_from_slice(b"\r\n"); + for (i, j) in self.headers.iter() { + res.extend_from_slice(i.as_bytes()); + res.extend_from_slice(b":"); + res.extend_from_slice(j.as_bytes()); + res.extend_from_slice(b"\r\n"); + } + res.extend_from_slice(b"\r\n"); + res.extend_from_slice(&self.body); + res } } + diff --git a/src/main.rs b/src/main.rs index 3d75b69..0852bb6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -186,15 +186,16 @@ fn handle(mut reader: BufReader<&mut TcpStream>) -> Result = reader - .bytes() - .take(s.1.parse::().unwrap()) - .collect::, io::Error>>() - .unwrap(); - // TODO test if it works - // FIXME deunwrap - // TODO handle body too large - request.add_body(body); + if request.method == Method::Post { + let body: Vec = reader + .bytes() + .take(s.1.parse::().unwrap()) + .collect::, io::Error>>() + .unwrap(); + // FIXME deunwrap + // TODO handle body too large + request.add_body(body); + } } dbg!(&request); @@ -220,14 +221,12 @@ fn get(path: &str) -> Result { .fold(String::from(""), |a, b| format!("{a}\n{b}")); let c = content("index", &ops); - Ok(Response::new(Status::Ok, vec![], c)) + Ok(Response::new(Status::Ok, vec![], c.into())) } // TODO favicon.ico - "/css" => Ok(Response::new(Status::Ok, vec![], String::from(STYLE))), - - "/faq" => Ok(Response::new(Status::Ok, vec![], String::from(FAQ))), - //"/favicon.ico" => Ok(Response::new(Status::Ok, vec![("content-type", "image/x-icon")], FAVICON)), - // TODO favicon + "/css" => Ok(Response::new(Status::Ok, vec![], String::from(STYLE).into())), + "/faq" => Ok(Response::new(Status::Ok, vec![], String::from(FAQ).into())), + "/favicon.ico" => Ok(Response::new(Status::Ok, vec![("content-type", "image/x-icon")], FAVICON.to_vec())), // list specific thread here // FIXME unwrap hell @@ -244,7 +243,7 @@ fn get(path: &str) -> Result { .fold(String::from(""), |a, b| format!("{a}\n{b}")); let c = content(&id.to_string(), &c); - Ok(Response::new(Status::Ok, vec![], c)) + Ok(Response::new(Status::Ok, vec![], c.into())) } } } @@ -266,7 +265,7 @@ fn post(request: Request) -> Result { Ok(Response::new( Status::SeeOther, vec![("location", "/")], - String::from(""), + vec![], )) } @@ -287,7 +286,7 @@ fn post(request: Request) -> Result { Ok(Response::new( Status::SeeOther, vec![("location", s)], - String::from(""), + vec![], )) } } @@ -335,7 +334,7 @@ fn main() { }; // handle request - stream.write(response.to_string().as_bytes()).unwrap(); + stream.write(&response.respond()).unwrap(); }); } } diff --git a/src/post.rs b/src/post.rs index 304f88a..bb7f30a 100644 --- a/src/post.rs +++ b/src/post.rs @@ -36,17 +36,6 @@ impl Thread { } } -//impl Thread { -// pub fn head(&self) -> String { -// let first = &self.0[0]; -// format!( -// "
{}
{}
", -// first.id, -// first.to_string(), -// ) -// } -//} - impl Post { pub fn new(id: u32, body: String) -> Self { Self { @@ -57,6 +46,7 @@ impl Post { } } +// TODO move this to `www/` impl fmt::Display for Post { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( diff --git a/src/www/favicon.ico b/src/www/favicon.ico index f1d213df04c1afea29e8af1016f12b9a6532ab9f..6bce58d8b28f414d17d6ab3fa7ef4515fc2e8347 100644 GIT binary patch literal 1253 zcmZQzU<5)CU}WH6IM2esAO>W22Kc%2a!GLknY^AJEUReyiR;at|NWtj|~ua~kjoEBu@5GEa2M^qi~{rl%<@t+?b zlV3_+=i}o$cJboHOU6QFyYKGUu_L1D*w(9ArgAnF24SnOUJ9c!={^KW4p1hG`=I#G8ciy#` zZ_0KrRbO&vn*Be+V>@>3imE!)%gN9}03Go8_VfS2m$zL3|NQs&w}qYEysyuG z{`|S-`!`o3hUA`&ck|NsmY0^AzP7E)1*Xuds$E}t_BZuw6Ud^sZ!>_i$e-?V#$9&x z|Mq-ok-mL$9fuikv~&Me*f-HR75{`mCt^rh)B(QCsVzq`BJ`}~fH uS515`Us7&Jee>3z;lX(V*$N}y{blCe-F$E7r%B$R^2*cI&t;ucLK6Vio@LJf literal 241886 zcmeI)v1*lP0LJlCGU}p3M@hh;gNuuUx1bmiqnjpPgS&`2IEZ4q2`-(42)zvH4LFK{ z+=MZCo0D=tO0n>q^zr=p{wYzgynW?+{y#s5q_f#i$N$XsXU9LT&p!OIHv4%toBeY9 zIsfH9k3Z+Xe)93#+U)mVXD6S3|H8?SBEeFipQ12$j-HedrbU;{Q_12$j-Hedrb zU;{Q_12$j-HedrbU;{Q_12$j-HedrbU;{Q_12$j-HedrbU;{Q_12$j-HedrbU;{Q_ z12$j-HedrbU;{Q_12$j-HedrbU;{Q_12$j-Hedt)*}&bqcgO43ugA-mFMs&wt5>ha zqeqX%`Sa)h^Y`ulYiara*VL6OSAO{B-*)%n#fx$2(j~Vq{<-z`?c1?RAN%|JV`F2( z1_}-A?Ch-4^e4ZUn>TN|ePR2>`}574H!Ib^-rn9=UthO@LIc~|+bgyG!NI}U+}w2g z!uI-K{_oF=XGr~7|2E+Jf4U9mf4bW*-dXyeZUg$C?)Lh3d;Qyh@BisGp#SM^@B82F z^=|{d|EJr4{-?XW?|-+~zYX~QpKb&CpYHa)|J`2yHsJezx((=my4#=D`~UFpaD4sx z^;ABOj*iBsPoMny|I*ig-@kwVRCfDz|M`aLhhP8S|MO^>_y2tN=g*&yTeohF+qZ8o z{kgTZHLhK|HqM+mK@&5gL{eybYzwhjSvz+{z z{&_9wpSM|JvvEfMyq5IO+pJ+ZxkLZFmh{itEV0=*qkmpY`sZ!du$8#acj%wjlKy#{B{myp^v`Qa|Gdo_mXka5&udBlyv-7u zjWhb^wWNREW(~{99s1|Bq<`LKiOt3t{qtJVKX0>!<>U_i^IFnBZ?nW^7Tb*VzY5Z|Gbv;&)ckFIk`jsyq5IO+bpr!IHP}FOZw++*07x1p?_XW z`sZzy*le89Kd&YI^EPW(PVUe@uO7Tb*!*X(m{&_9wpSM|JvvEfMyq5IO+pJ+ZxkLZFmh{it zEV0=*qkmpY`sZ!du$8#acj%wjlKy#{ zB{myp^v`Qa|Gdo_mXka5&udBlyv-7ujWhb^wWNREW(~{99s1|Bq<`LKiOt3t{qtJV zKX0>!<>U_i^IFnBZ?nW^7Tb*VzY5Z|Gbv;&)ckFIk`js zyq5IO+bpr!IHP}FOZw++*07x1p?_XW`sZzy*le89Kd&YI^EPW(PVUe@uO7Tb*!*X(m{&_9w zpSM|JvvEfMyq5IO+pJ+ZxkLZFmh{itEV0=*qkmpY`sZ!du$*~PbHDig=zqEm=zqG~ z>)-A5Zv(#nr`v%3r@OuHf4A4a4fy__ZUg$C?)JX_-CqAT;QN2N4d{Qm+xz}^d;Qyh z@BisGp#SM^zpC&5&!0d0_5X#h{h#kY_kVPB^qsHB@BXVVU%vSLzoqRL{;yuWIvzZD zaMHrOhadSl|9-Tst*vqP>{-A6r_jO0ix+?B-v4av-o1O{!i5WNU)X-(-=F