added favicon, sending binary data in response,

ignoring body with non-POST methods, better Response methods (.respond() in particular)
doctorpavel
Dawid J. Kubis 2 years ago
parent e08c368365
commit 1651126606

@ -1,7 +1,4 @@
### TODO: # kchan
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
### Rules ### Rules
+ single page + single page

@ -76,6 +76,6 @@ impl From<HandlingError> for Response {
HandlingError::ServerError(e) => Status::from(e), HandlingError::ServerError(e) => Status::from(e),
HandlingError::Io(e) => Status::InternalServerError, HandlingError::Io(e) => Status::InternalServerError,
}; };
Response::new(status, vec![], status.message().to_string()) Response::new(status, vec![], status.message().into())
} }
} }

@ -18,7 +18,7 @@ pub struct Request {
pub struct Response { pub struct Response {
pub status: Status, pub status: Status,
pub headers: Vec<(String, String)>, pub headers: Vec<(String, String)>,
pub body: String, // make into Option<Vec<u8>> pub body: Vec<u8>, // make into Option<Vec<u8>>
} }
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
@ -31,7 +31,7 @@ pub enum Status {
InternalServerError = 500, InternalServerError = 500,
} }
#[derive(Debug)] #[derive(Debug, PartialEq)]
pub enum Method { pub enum Method {
Get, Get,
Post, Post,
@ -114,7 +114,7 @@ impl TryFrom<Vec<String>> for Request {
} }
impl Response { 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<u8>) -> Self {
Self { Self {
status, status,
headers: headers headers: headers
@ -124,24 +124,24 @@ impl Response {
body, body,
} }
} }
}
impl fmt::Display for Response { pub fn respond(&self) -> Vec<u8> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut res = vec![];
let headers: String = self res.extend_from_slice(HTTP_VERSION.as_bytes());
.headers res.extend_from_slice(b" ");
.iter() res.extend_from_slice(&(self.status as i32).to_string().as_bytes()); // network endianness
.map(|x| format!("{}:{}\n", x.0, x.1)) res.extend_from_slice(b" ");
.fold(String::from(""), |a, b| format!("{}{}", a, b)); // possibly slow res.extend_from_slice(self.status.message().as_bytes());
res.extend_from_slice(b"\r\n");
write!( for (i, j) in self.headers.iter() {
f, res.extend_from_slice(i.as_bytes());
"{} {} {}\n{}\n\n{}", res.extend_from_slice(b":");
HTTP_VERSION, res.extend_from_slice(j.as_bytes());
self.status as i32, res.extend_from_slice(b"\r\n");
self.status.message(), }
headers, res.extend_from_slice(b"\r\n");
self.body, res.extend_from_slice(&self.body);
) res
} }
} }

@ -186,16 +186,17 @@ fn handle(mut reader: BufReader<&mut TcpStream>) -> Result<Response, HandlingErr
.iter() .iter()
.find(|(a, b)| a.to_lowercase() == "content-length") .find(|(a, b)| a.to_lowercase() == "content-length")
{ {
if request.method == Method::Post {
let body: Vec<u8> = reader let body: Vec<u8> = reader
.bytes() .bytes()
.take(s.1.parse::<usize>().unwrap()) .take(s.1.parse::<usize>().unwrap())
.collect::<Result<Vec<u8>, io::Error>>() .collect::<Result<Vec<u8>, io::Error>>()
.unwrap(); .unwrap();
// TODO test if it works
// FIXME deunwrap // FIXME deunwrap
// TODO handle body too large // TODO handle body too large
request.add_body(body); request.add_body(body);
} }
}
dbg!(&request); dbg!(&request);
match request.method { match request.method {
@ -220,14 +221,12 @@ fn get(path: &str) -> Result<Response, HandlingError> {
.fold(String::from(""), |a, b| format!("{a}\n{b}")); .fold(String::from(""), |a, b| format!("{a}\n{b}"));
let c = content("index", &ops); let c = content("index", &ops);
Ok(Response::new(Status::Ok, vec![], c)) Ok(Response::new(Status::Ok, vec![], c.into()))
} }
// TODO favicon.ico // TODO favicon.ico
"/css" => Ok(Response::new(Status::Ok, vec![], String::from(STYLE))), "/css" => Ok(Response::new(Status::Ok, vec![], String::from(STYLE).into())),
"/faq" => Ok(Response::new(Status::Ok, vec![], String::from(FAQ).into())),
"/faq" => Ok(Response::new(Status::Ok, vec![], String::from(FAQ))), "/favicon.ico" => Ok(Response::new(Status::Ok, vec![("content-type", "image/x-icon")], FAVICON.to_vec())),
//"/favicon.ico" => Ok(Response::new(Status::Ok, vec![("content-type", "image/x-icon")], FAVICON)),
// TODO favicon
// list specific thread here // list specific thread here
// FIXME unwrap hell // FIXME unwrap hell
@ -244,7 +243,7 @@ fn get(path: &str) -> Result<Response, HandlingError> {
.fold(String::from(""), |a, b| format!("{a}\n{b}")); .fold(String::from(""), |a, b| format!("{a}\n{b}"));
let c = content(&id.to_string(), &c); 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<Response, HandlingError> {
Ok(Response::new( Ok(Response::new(
Status::SeeOther, Status::SeeOther,
vec![("location", "/")], vec![("location", "/")],
String::from(""), vec![],
)) ))
} }
@ -287,7 +286,7 @@ fn post(request: Request) -> Result<Response, HandlingError> {
Ok(Response::new( Ok(Response::new(
Status::SeeOther, Status::SeeOther,
vec![("location", s)], vec![("location", s)],
String::from(""), vec![],
)) ))
} }
} }
@ -335,7 +334,7 @@ fn main() {
}; };
// handle request // handle request
stream.write(response.to_string().as_bytes()).unwrap(); stream.write(&response.respond()).unwrap();
}); });
} }
} }

@ -36,17 +36,6 @@ impl Thread {
} }
} }
//impl Thread {
// pub fn head(&self) -> String {
// let first = &self.0[0];
// format!(
// "<article><div><span class=\"info\">{}</span></div>{}</article>",
// first.id,
// first.to_string(),
// )
// }
//}
impl Post { impl Post {
pub fn new(id: u32, body: String) -> Self { pub fn new(id: u32, body: String) -> Self {
Self { Self {
@ -57,6 +46,7 @@ impl Post {
} }
} }
// TODO move this to `www/`
impl fmt::Display for Post { impl fmt::Display for Post {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!( write!(

Binary file not shown.

Before

Width:  |  Height:  |  Size: 236 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Loading…
Cancel
Save