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:
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

@ -76,6 +76,6 @@ impl From<HandlingError> 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())
}
}

@ -18,7 +18,7 @@ pub struct Request {
pub struct Response {
pub status: Status,
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)]
@ -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<Vec<String>> 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<u8>) -> 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<u8> {
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
}
}

@ -186,16 +186,17 @@ fn handle(mut reader: BufReader<&mut TcpStream>) -> Result<Response, HandlingErr
.iter()
.find(|(a, b)| a.to_lowercase() == "content-length")
{
if request.method == Method::Post {
let body: Vec<u8> = reader
.bytes()
.take(s.1.parse::<usize>().unwrap())
.collect::<Result<Vec<u8>, io::Error>>()
.unwrap();
// TODO test if it works
// FIXME deunwrap
// TODO handle body too large
request.add_body(body);
}
}
dbg!(&request);
match request.method {
@ -220,14 +221,12 @@ fn get(path: &str) -> Result<Response, HandlingError> {
.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<Response, HandlingError> {
.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<Response, HandlingError> {
Ok(Response::new(
Status::SeeOther,
vec![("location", "/")],
String::from(""),
vec![],
))
}
@ -287,7 +286,7 @@ fn post(request: Request) -> Result<Response, HandlingError> {
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();
});
}
}

@ -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 {
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!(

Binary file not shown.

Before

Width:  |  Height:  |  Size: 236 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Loading…
Cancel
Save