96 lines
2.7 KiB
Rust
96 lines
2.7 KiB
Rust
use std::convert::Infallible;
|
|
use std::path::Path;
|
|
|
|
use hyper::service::{make_service_fn, service_fn};
|
|
use hyper::{Body, Method, Request, Response, Server, StatusCode};
|
|
use pulldown_cmark::{html, Options, Parser};
|
|
|
|
async fn hello_world(req: Request<Body>) -> Result<Response<Body>, Infallible> {
|
|
println!("New request to '{}'", req.uri());
|
|
|
|
let path = &req
|
|
.uri()
|
|
.path()[1..] // Remove the first "/". We don't need it
|
|
.replace("..", "") // Don't allow to go up in the hierarchy
|
|
;
|
|
|
|
// Get the first part so we can route it
|
|
let until = path.find('/').unwrap_or(path.len());
|
|
|
|
let mut response = Response::new(Body::empty());
|
|
|
|
match (req.method(), &path[..until]) {
|
|
(&Method::GET, "blog") => {
|
|
*response.body_mut() = Body::from(path_access(path));
|
|
}
|
|
(_, path) => {
|
|
*response.body_mut() = Body::from(format!("Access to '{path}' isn't allowed."));
|
|
*response.status_mut() = StatusCode::FORBIDDEN;
|
|
}
|
|
}
|
|
|
|
Ok(response)
|
|
}
|
|
|
|
fn path_access(path_str: &str) -> String {
|
|
let path = Path::new(path_str);
|
|
|
|
if path.is_file() {
|
|
file_to_md(path_str)
|
|
} else if path.is_dir() {
|
|
list_directory(path_str)
|
|
} else {
|
|
format!("Path '{path_str}' doesn't exist!")
|
|
}
|
|
}
|
|
|
|
fn list_directory(path_str: &str) -> String {
|
|
let folder = match Path::new(path_str).read_dir() {
|
|
Err(_) => return "Failed to read directory.".to_string(),
|
|
Ok(x) => x,
|
|
};
|
|
|
|
let mut string = String::new();
|
|
|
|
for entry in folder {
|
|
let entry = match entry {
|
|
Err(_) => return "Failed to read entry".to_string(),
|
|
Ok(x) => x,
|
|
};
|
|
|
|
if let Some(filename) = entry.file_name().to_str() {
|
|
string.push_str(format!(r#"<a href="{path_str}/{0}">{0}</a><br/>"#, filename).as_str());
|
|
}
|
|
}
|
|
|
|
string
|
|
}
|
|
|
|
fn file_to_md(path: &str) -> String {
|
|
let file = std::fs::read_to_string(path).unwrap_or("Couldn't read file.".to_string());
|
|
|
|
//let mut options = Options::empty();
|
|
//options.insert(Options::ENABLE_STRIKETHROUGH);
|
|
let parser = Parser::new_ext(file.as_str(), Options::ENABLE_STRIKETHROUGH);
|
|
|
|
// Write to String buffer.
|
|
let mut html_output: String = String::with_capacity(file.len() * 3 / 2);
|
|
html::push_html(&mut html_output, parser);
|
|
|
|
html_output
|
|
}
|
|
|
|
#[tokio::main]
|
|
async fn main() {
|
|
let addr = ([127, 0, 0, 1], 3000).into();
|
|
|
|
let make_svc = make_service_fn(|_conn| async { Ok::<_, Infallible>(service_fn(hello_world)) });
|
|
|
|
let server = Server::bind(&addr).serve(make_svc);
|
|
|
|
println!("Server listening on: http://{}", addr);
|
|
if let Err(e) = server.await {
|
|
eprintln!("server error: {}", e);
|
|
}
|
|
}
|