improved id's, fixed some bugs, changed database structure, improved errors,

added logging, created html trait, organized and formatted code
doctorpavel
Dawid J. Kubis 3 years ago
parent c6088fbb79
commit 407f5e427a

155
Cargo.lock generated

@ -23,25 +23,6 @@ dependencies = [
"winapi",
]
[[package]]
name = "async-mutex"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "479db852db25d9dbf6204e6cb6253698f175c15726470f78af0d918e99d6156e"
dependencies = [
"event-listener",
]
[[package]]
name = "async-rwlock"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "261803dcc39ba9e72760ba6e16d0199b1eef9fc44e81bffabbebb9f5aea3906c"
dependencies = [
"async-mutex",
"event-listener",
]
[[package]]
name = "atty"
version = "0.2.14"
@ -98,40 +79,6 @@ version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "cached"
version = "0.33.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f66c8f6ae13abbdc12268879b8070a441777b69157fb7653b4c7da7f2610c25d"
dependencies = [
"async-mutex",
"async-rwlock",
"cached_proc_macro",
"cached_proc_macro_types",
"hashbrown",
"once_cell",
"thiserror",
"tokio",
]
[[package]]
name = "cached_proc_macro"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc8de7b947777686ee8f3c11f4c3e58c296d6bc598d9b2286a80a9404a538ff8"
dependencies = [
"cached_proc_macro_types",
"darling",
"quote",
"syn",
]
[[package]]
name = "cached_proc_macro_types"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a4f925191b4367301851c6d99b09890311d74b0d43f274c0b34c86d308a3663"
[[package]]
name = "cfg-if"
version = "1.0.0"
@ -160,7 +107,7 @@ dependencies = [
"ansi_term",
"atty",
"bitflags",
"strsim 0.8.0",
"strsim",
"textwrap",
"unicode-width",
"vec_map",
@ -225,41 +172,6 @@ dependencies = [
"lazy_static",
]
[[package]]
name = "darling"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0d720b8683f8dd83c65155f0530560cba68cd2bf395f6513a483caee57ff7f4"
dependencies = [
"darling_core",
"darling_macro",
]
[[package]]
name = "darling_core"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a340f241d2ceed1deb47ae36c4144b2707ec7dd0b649f894cb39bb595986324"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"strsim 0.10.0",
"syn",
]
[[package]]
name = "darling_macro"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72c41b3b7352feb3211a0d743dc5700a4e3b60f51bd2b368892d1e0f9a95f44b"
dependencies = [
"darling_core",
"quote",
"syn",
]
[[package]]
name = "deflate"
version = "1.0.0"
@ -275,12 +187,6 @@ version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
[[package]]
name = "event-listener"
version = "2.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71"
[[package]]
name = "exr"
version = "1.4.1"
@ -322,12 +228,6 @@ dependencies = [
"spin",
]
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "fs2"
version = "0.4.3"
@ -388,12 +288,6 @@ version = "1.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7"
[[package]]
name = "hashbrown"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c21d40587b92fa6a6c6e3c1bdbf87d75511db5672f9c93175574b3a00df1758"
[[package]]
name = "heck"
version = "0.3.3"
@ -412,12 +306,6 @@ dependencies = [
"libc",
]
[[package]]
name = "ident_case"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "image"
version = "0.24.1"
@ -485,7 +373,6 @@ name = "kchan"
version = "0.1.0"
dependencies = [
"bincode",
"cached",
"image",
"lazy_static",
"log",
@ -623,12 +510,6 @@ dependencies = [
"libc",
]
[[package]]
name = "once_cell"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9"
[[package]]
name = "parking_lot"
version = "0.11.2"
@ -674,12 +555,6 @@ dependencies = [
"syn",
]
[[package]]
name = "pin-project-lite"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c"
[[package]]
name = "png"
version = "0.17.5"
@ -894,12 +769,6 @@ version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "structopt"
version = "0.3.25"
@ -1003,28 +872,6 @@ dependencies = [
"winapi",
]
[[package]]
name = "tokio"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee"
dependencies = [
"num_cpus",
"pin-project-lite",
"tokio-macros",
]
[[package]]
name = "tokio-macros"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "unicode-segmentation"
version = "1.8.0"

@ -15,7 +15,6 @@ lazy_static = "1.4.0"
sled = "0.34.7"
bincode = "1.3.3"
serde = { version = "1.0.136", features = ["derive"] }
cached = "0.33.0"
log = "0.4.14"
simplelog = "0.11.2"
image = "0.24.1"

@ -26,7 +26,7 @@ pub enum InternalError {
#[derive(Debug, Error)]
pub enum HandlingError {
#[error("client error: {0}")]
ClientError(RequestError),
ClientError(#[from] RequestError),
#[error("server error: {0}")]
ServerError(InternalError),
ServerError(#[from] InternalError),
}

@ -0,0 +1,9 @@
// statically linked index and favicon
pub const INDEX: &'static str = include_str!("www/index.html");
//pub const FAVICON: &'static [u8] = include_bytes!("www/favicon.ico");
pub const STYLE: &'static str = include_str!("www/style.css");
pub const FAQ: &'static str = include_str!("www/faq.html");
pub trait Htmlizable {
fn to_html(&self) -> String;
}

@ -2,7 +2,7 @@ use std::collections::HashMap;
use std::fmt;
use std::str::{FromStr, Lines};
use crate::errors::RequestError;
use crate::errors::{HandlingError, RequestError};
const HTTP_VERSION: &'static str = "HTTP/1.1";
@ -97,6 +97,12 @@ impl Response {
}
}
impl From<HandlingError> for Response {
fn from(err: HandlingError) -> Self {
todo!();
}
}
impl fmt::Display for Response {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let headers: String = self

@ -1,8 +1,12 @@
#![feature(int_log)]
mod errors;
mod html;
mod http;
mod post;
use crate::errors::{HandlingError, InternalError, RequestError};
use crate::html::{FAQ, INDEX, STYLE};
use crate::http::{Request, Response, Status};
use crate::post::{Post, Thread};
@ -13,21 +17,15 @@ use std::path::PathBuf;
use std::str;
use std::str::from_utf8;
use std::sync::{Arc, Mutex, MutexGuard};
use std::thread::JoinHandle;
use bincode::{deserialize, serialize};
use cached::proc_macro::cached;
use lazy_static::lazy_static;
use log::*;
use simplelog::*;
use structopt::StructOpt;
use threadpool::ThreadPool;
// statically linked index and favicon
const INDEX: &'static str = include_str!("www/index.html");
const FAVICON: &'static [u8] = include_bytes!("www/favicon.ico");
const STYLE: &'static str = include_str!("www/style.css");
const FAQ: &'static str = include_str!("www/faq.html");
// represents command line arguments
#[derive(StructOpt, Debug)]
struct Opt {
@ -51,15 +49,20 @@ lazy_static! {
#[derive(Debug)]
struct State {
db: sled::Db,
id_counter: u64,
id_counter: u32,
// cache here?
}
impl State {
fn next_id(&mut self) -> u64 {
fn next_id(&mut self) -> String {
let id = self.id_counter;
self.id_counter += 1;
id
// TODO improve this
// means the highest possible id is 999_999_999, then it loops back to zero
// NOTE this could technically be used to limit the storage required,
// might possibly be a good feature
self.id_counter = (self.id_counter + 1) % 1_000_000_000;
let width = u32::MAX.log10() as usize; // happens to be 9 in this case
format!("{id:0width$}")
}
}
@ -74,12 +77,15 @@ fn handle(request: &str, state: Arc<Mutex<State>>) -> Response {
match request.method.as_str() {
"GET" => match get(&request.uri, state) {
Ok(s) => s,
Err(e) => Response::new(Status::NotFound, vec![], e.to_string()),
Err(e) => Response::new(Status::NotFound, vec![], dbg!(e).to_string()),
},
"POST" => match post(request, state) {
Ok(s) => s,
Err(e) => Response::new(Status::Ok, vec![], "".to_string()),
},
"POST" => post(request, state),
// check admin hash
"DELETE" => Response::new(Status::Ok, vec![], "".to_string()),
_ => Response::new(Status::Ok, vec![], "".to_string()),
_ => Response::new(Status::Ok, vec![], RequestError::BadRequest.to_string()),
}
}
@ -115,7 +121,7 @@ fn get(path: &str, state: MutexGuard<State>) -> Result<Response, HandlingError>
&deserialize::<Thread>(
&state
.db
.get(&s.as_bytes())
.get(&s[1..])
.map_err(|_| HandlingError::ServerError(InternalError::DatabaseReadError))?
.ok_or(HandlingError::ClientError(RequestError::NotFound))?,
)
@ -128,29 +134,54 @@ fn get(path: &str, state: MutexGuard<State>) -> Result<Response, HandlingError>
}
}
fn post(request: Request, mut state: MutexGuard<State>) -> Response {
fn post(request: Request, mut state: MutexGuard<State>) -> Result<Response, HandlingError> {
match request.uri.as_str() {
// means we wish to create a new thread
"/" => {
// first we increment id
let id = state.next_id();
// TODO fix unwrap
let content = dbg!(request.form().unwrap());
let id = state.next_id();
let thread = Thread(vec![Post::new(
id,
None,
&id,
String::from(*content.get("content").unwrap()),
)]);
state.db.insert(&id, serialize(&thread).unwrap()).unwrap();
info!("Created new thread, id: {}", id);
// TODO add redirect
Ok(Response::new(Status::Ok, vec![], String::from("")))
}
// means we wish to post in specific thread
s => {
// first we increment id
let id = state.next_id();
let content = dbg!(request.form().unwrap());
let post = Post::new(&id, String::from(*content.get("content").unwrap()));
let mut thread = deserialize::<Thread>(
&state
.db
.remove(&s[1..])
.map_err(|_| HandlingError::ServerError(InternalError::DatabaseWriteError))?
.ok_or(HandlingError::ClientError(RequestError::NotFound))?,
)
.unwrap();
thread.0.push(post);
state
.db
.insert(id.to_ne_bytes(), serialize(&thread).unwrap())
.insert(&s[1..], serialize(&thread).unwrap())
.unwrap();
// make this less weird
info!("Added new post to thread {}", s);
Response::new(Status::Ok, vec![], String::from(""))
// TODO add redirect
Ok(Response::new(Status::Ok, vec![], String::from("")))
}
// means we wish to post in specific thread
s => Response::new(Status::Ok, vec![], String::from("")),
}
}
@ -171,7 +202,7 @@ fn main() {
let pool = ThreadPool::new(num_cpus::get());
// setup logger
TermLogger::init(
LevelFilter::Warn,
LevelFilter::Info,
Config::default(),
TerminalMode::Mixed,
ColorChoice::Auto,
@ -189,10 +220,11 @@ fn main() {
let mut stream = match stream {
Ok(s) => s,
Err(e) => {
eprintln!("failed connection: {}", e);
warn!("Failed connection: {}", e);
continue;
}
};
let state = Arc::clone(&state);
pool.execute(move || {
let ip = stream.peer_addr().unwrap();
@ -202,6 +234,7 @@ fn main() {
stream.read(&mut buffer).unwrap();
// NOTE possibly problematic when we cosider images
let text = str::from_utf8(&buffer).unwrap().trim_matches(0 as char);
// ^-- gets rid of null at the end of buffer

@ -2,15 +2,15 @@ use std::fmt;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Image {
pub filename: String,
pub img: Box<[u8]>,
}
//#[derive(Debug, Clone, Serialize, Deserialize)]
//pub struct Image {
// pub filename: String,
// pub img: Box<[u8]>,
//}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Post {
pub id: u64,
pub id: String,
//pub img: Option<Image>,
pub body: String,
}
@ -30,9 +30,9 @@ impl Thread {
}
impl Post {
pub fn new(id: u64, img: Option<Image>, body: String) -> Self {
pub fn new(id: &str, body: String) -> Self {
Self {
id,
id: id.to_string(),
//img,
body,
}

Loading…
Cancel
Save