added support for the DELTE method to moderate the board,

removed authorization code as it can be handled from nginx
updated dependencies, resolved some warnings
doctorpavel
Dawid J. Kubis
parent 06d2d7a957
commit 7cf755b47b

38
Cargo.lock generated

@ -186,7 +186,6 @@ dependencies = [
"structopt",
"thiserror",
"threadpool",
"urlencoding",
]
[[package]]
@ -197,15 +196,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.144"
version = "0.2.146"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1"
checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b"
[[package]]
name = "lock_api"
version = "0.4.9"
version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16"
dependencies = [
"autocfg",
"scopeguard",
@ -213,12 +212,9 @@ dependencies = [
[[package]]
name = "log"
version = "0.4.17"
version = "0.4.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if",
]
checksum = "518ef76f2f87365916b142844c16d8fefd85039bc5699050210a7778ee1cd1de"
[[package]]
name = "memoffset"
@ -299,9 +295,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.59"
version = "1.0.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6aeca18b86b413c660b781aa319e4e2648a3e6f9eadc9b47e9038e6fe9f3451b"
checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406"
dependencies = [
"unicode-ident",
]
@ -332,18 +328,18 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "serde"
version = "1.0.163"
version = "1.0.164"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2"
checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.163"
version = "1.0.164"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e"
checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68"
dependencies = [
"proc-macro2",
"quote",
@ -484,9 +480,9 @@ dependencies = [
[[package]]
name = "time"
version = "0.3.21"
version = "0.3.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f3403384eaacbca9923fa06940178ac13e4edb725486d70e8e15881d0c836cc"
checksum = "ea9e1b3cf1243ae005d9e74085d4d542f3125458f3a81af210d901dcd7411efd"
dependencies = [
"itoa",
"libc",
@ -529,12 +525,6 @@ version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
[[package]]
name = "urlencoding"
version = "2.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8db7427f936968176eaa7cdf81b7f98b980b18495ec28f1b5791ac3bfe3eea9"
[[package]]
name = "utf8-width"
version = "0.1.6"

@ -17,7 +17,6 @@ serde = { version = "1.0.136", features = ["derive"] }
log = "0.4.17"
simplelog = "0.12.1"
html-escape = "0.2.13"
urlencoding = "2.1.2"
#ctrlc = "3.3.1"
#urlencoding = "2.1.2"
#image = "0.24.6"

@ -13,8 +13,6 @@ pub enum RequestError {
NotFound,
#[error("unused method")]
UnusedMethod,
#[error("request not authorized, incorred hash: {0}")]
NotAuthorized(String),
#[error("urldecoding error")]
UrlDecodeErr(#[from] FromUtf8Error),
#[error("bad request")]
@ -59,7 +57,6 @@ impl From<RequestError> for Status {
RequestError::NotAForm => Status::BadRequest,
RequestError::NotFound => Status::NotFound,
RequestError::UnusedMethod => Status::BadRequest,
RequestError::NotAuthorized(_) => Status::Unauthorized,
RequestError::UrlDecodeErr(_) => Status::BadRequest,
RequestError::BadRequest => Status::BadRequest,
RequestError::MissingBody => Status::BadRequest,
@ -72,7 +69,7 @@ impl From<HandlingError> for Response {
let status = match err {
HandlingError::ClientError(e) => Status::from(e),
HandlingError::ServerError(e) => Status::from(e),
HandlingError::Io(e) => Status::InternalServerError,
HandlingError::Io(_) => Status::InternalServerError,
};
Response::new(status, vec![], status.message().into())
}

@ -1,9 +1,6 @@
use std::fmt;
use std::str::{FromStr, Lines};
use crate::errors::{HandlingError, RequestError};
use html_escape::encode_text;
use crate::errors::RequestError;
const HTTP_VERSION: &'static str = "HTTP/1.1";
@ -28,7 +25,6 @@ pub enum Status {
SeeOther = 303,
NotFound = 404,
BadRequest = 400,
Unauthorized = 401,
InternalServerError = 500,
}
@ -57,7 +53,6 @@ impl Status {
Self::Ok => "OK",
Self::NotFound => "NOT FOUND",
Self::BadRequest => "BAD REQUEST",
Self::Unauthorized => "UNAUTHORIZED",
Self::InternalServerError => "INTERNAL SERVER ERROR",
Self::SeeOther => "SEE OTHER",
}
@ -121,7 +116,7 @@ impl TryFrom<&Request> for Form {
let content = String::from_utf8_lossy(&body[pos..temp]).to_string();
//let content = encode_text(&content.trim().to_string()).to_string();
// do that later
dbg!(&content);
//dbg!(&content);
// good so far
@ -140,7 +135,7 @@ impl TryFrom<&Request> for Form {
+ pos;
let image = if &body[pos..temp] == b"\r\n" {
dbg!("no image");
//dbg!("no image");
None
} else {
Some(body[pos..temp].to_owned())
@ -154,17 +149,6 @@ impl Request {
pub fn add_body(&mut self, body: Vec<u8>) {
self.body = Some(body);
}
// pub fn form(&self) -> Result<HashMap<&str, String>, RequestError> {
// let mut hashmap = HashMap::new();
// dbg!(&self.body);
// for mut x in self.body.split("&").map(|x| x.split("=")) {
// hashmap.insert(
// x.next().ok_or(RequestError::NotAForm)?,
// decode(x.next().ok_or(RequestError::NotAForm)?)?.into_owned().replace("+", " "),
// );
// }
// Ok(hashmap)
// }
}
impl TryFrom<Vec<String>> for Request {

@ -6,15 +6,11 @@ use crate::errors::{HandlingError, RequestError};
use crate::http::{Form, Request, Response, Status};
use crate::post::{Post, Thread};
use std::error::Error;
use std::io;
use std::io::{BufRead, BufReader, Read, Write};
use std::net::{SocketAddr, TcpListener, TcpStream};
use std::path::{Path, PathBuf};
use std::path::PathBuf;
use std::str;
use std::str::from_utf8;
use std::sync::{Arc, RwLock};
use std::thread::JoinHandle;
use bincode::{deserialize, serialize};
use errors::DatabaseError;
@ -25,14 +21,13 @@ use log::*;
use simplelog::*;
use structopt::StructOpt;
use threadpool::ThreadPool;
use urlencoding::decode;
// use this instead of hard-coding
type ID_TYPE = u32;
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");
//type ID_TYPE = u32;
pub const INDEX: &str = include_str!("www/index.html");
pub const FAVICON: &[u8] = include_bytes!("www/favicon.ico");
pub const STYLE: &str = include_str!("www/style.css");
pub const FAQ: &str = include_str!("www/faq.html");
// represents command line arguments
#[derive(StructOpt, Debug)]
@ -40,9 +35,6 @@ struct Opt {
#[structopt(short, long, default_value = "8000")]
port: u16,
#[structopt(short, long)]
admin_hash: Option<String>,
#[structopt(short, long, default_value = "data")]
database: PathBuf,
}
@ -87,6 +79,7 @@ fn get_thread(id: u32) -> Result<Vec<Post>, DatabaseError> {
.and_then(|x| deserialize::<Thread>(&x).map_err(|_| DatabaseError::SerError))?
.into_iter()
.map(|x| get_post(x))
.filter(|x| x.is_ok())
.collect()
// let thread = THREADS.get(id.to_be_bytes()).and_then()
}
@ -104,14 +97,6 @@ fn next_id() -> Result<u32, DatabaseError> {
.map_err(|e| DatabaseError::from(e))
}
/// returns current id
/// not used
fn get_id() -> Result<u32, DatabaseError> {
let s = DB.get(b"id")?.unwrap();
let buf: [u8; 4] = (*s).try_into().unwrap();
Ok(u32::from_be_bytes(buf))
}
/// lists all threads
fn list_threads() -> Result<Vec<Post>, DatabaseError> {
THREADS
@ -155,6 +140,15 @@ fn add_post(mut post: Post, thread_id: u32) -> Result<(), DatabaseError> {
Ok(())
}
fn delete_post(id: u32) -> Result<(), DatabaseError> {
POSTS.remove(id.to_be_bytes())?;
if THREADS.contains_key(id.to_be_bytes())? {
THREADS.remove(id.to_be_bytes())?;
} else {
}
Ok(())
}
fn add_thread(mut post: Post) -> Result<(), DatabaseError> {
let id = next_id()?;
let thread = Thread::new(id);
@ -205,9 +199,7 @@ fn handle(mut reader: BufReader<&mut TcpStream>) -> Result<Response, HandlingErr
Method::Get => get(&request.uri),
Method::Post => post(request),
// TODO check admin hash
_ => Ok(Response::from(HandlingError::from(
RequestError::BadRequest,
))),
Method::Delete => delete(&request.uri),
}
}
@ -269,12 +261,7 @@ fn post(request: Request) -> Result<Response, HandlingError> {
let form = Form::try_from(&request)?;
let mut post = Post::new(
0,
dbg!(encode_text(form.content.trim()))
.replace("\r\n", "<br>")
.to_string(),
);
let mut post = Post::new(0, encode_text(form.content.trim()).replace("\r\n", "<br>"));
post.img = form.image;
match request.uri.as_str() {
@ -294,8 +281,8 @@ fn post(request: Request) -> Result<Response, HandlingError> {
// means we wish to post in specific thread
s => {
let id = s
.trim_start_matches("/")
.split("/")
.trim_start_matches('/')
.split('/')
.next()
.unwrap()
.parse::<u32>()
@ -314,8 +301,17 @@ fn post(request: Request) -> Result<Response, HandlingError> {
}
}
fn delete(path: &str) -> Response {
todo!();
fn delete(path: &str) -> Result<Response, HandlingError> {
let id = path
.trim_start_matches("/")
.parse::<u32>()
.map_err(|_| RequestError::NotFound)?;
delete_post(id)?;
Ok(Response::new(
Status::SeeOther,
vec![("location", "/")],
vec![],
))
}
fn content(name: &str, main: &str) -> String {
@ -323,11 +319,6 @@ fn content(name: &str, main: &str) -> String {
}
fn main() {
// bind listener to local adress and port
let listener =
TcpListener::bind(("127.0.0.1", OPT.port)).expect("Cannot bind to specified port.");
// create threadpool for incoming requests
let pool = ThreadPool::new(num_cpus::get());
// setup logger
TermLogger::init(
LevelFilter::Info,
@ -337,6 +328,15 @@ fn main() {
)
.expect("failed to setup logger");
// bind listener to local adress and port
let listener =
TcpListener::bind(("127.0.0.1", OPT.port)).expect("Cannot bind to specified port.");
info!("listening on port {}", OPT.port);
// create threadpool for incoming requests
let pool = ThreadPool::new(num_cpus::get());
// wait for requests
for stream in listener.incoming() {
let mut stream = match stream {
@ -352,11 +352,14 @@ fn main() {
let response = match handle(reader) {
Ok(s) => s,
Err(e) => Response::from(dbg!(e)),
Err(e) => {
warn!("{e}");
Response::from(e)
}
};
// handle request
stream.write(&response.respond()).unwrap();
stream.write_all(&response.respond()).unwrap();
});
}
}

Loading…
Cancel
Save