0.8.0: add user configuration.
This commit is contained in:
parent
53b47ad522
commit
c2e35fcf5c
4 changed files with 112 additions and 21 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,3 +1,4 @@
|
|||
/target
|
||||
/src/content
|
||||
index.html
|
||||
*settings.toml
|
||||
|
|
9
Cargo.lock
generated
9
Cargo.lock
generated
|
@ -2,10 +2,17 @@
|
|||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "frostwalker"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "17cbf58e19f2bda088d8c4c95a46b41895375e15a2d63dd686a4273f8c43d46b"
|
||||
|
||||
[[package]]
|
||||
name = "herb"
|
||||
version = "0.7.3"
|
||||
version = "0.8.0"
|
||||
dependencies = [
|
||||
"frostwalker",
|
||||
"packeteer",
|
||||
]
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
[package]
|
||||
name = "herb"
|
||||
version = "0.7.3"
|
||||
version = "0.8.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
frostwalker = "0.1.1"
|
||||
packeteer = { version = "0.5.2", features = ["http1"] }
|
||||
|
|
120
src/main.rs
120
src/main.rs
|
@ -6,6 +6,7 @@ use std::fs::File;
|
|||
use std::string::{String};
|
||||
use std::process::Command;
|
||||
use packeteer::http1::*;
|
||||
use frostwalker;
|
||||
use packeteer::{generate_kvheader, unwrap_url_into_segments};
|
||||
|
||||
struct Resource {
|
||||
|
@ -18,10 +19,24 @@ struct Resource {
|
|||
struct GetPageResult {
|
||||
is500: bool,
|
||||
is502: bool,
|
||||
is403: bool,
|
||||
contents: Vec<u8>,
|
||||
iscgi: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Settings {
|
||||
cgi: bool,
|
||||
index_generation: bool,
|
||||
address: String,
|
||||
}
|
||||
|
||||
impl Settings {
|
||||
fn new() -> Settings {
|
||||
return Settings { cgi: true, index_generation: true, address: "0.0.0.0:8080".to_string()};
|
||||
}
|
||||
}
|
||||
|
||||
fn process_cgi(filename: String) -> Option<Vec<u8>> {
|
||||
// This is gonna be the boggiest implementation of CGI that anyone
|
||||
// has ever seen in the history of the fucking world
|
||||
|
@ -154,9 +169,6 @@ fn detect_media_type(filename: String) -> String {
|
|||
"txt" => "text/plain".to_string(),
|
||||
"html" => "text/html".to_string(),
|
||||
"htm" => "text/html".to_string(),
|
||||
"cgi" => "text/html".to_string(),
|
||||
".error_server_404" => "text/html".to_string(),
|
||||
".error_server_501" => "text/html".to_string(),
|
||||
_ => "application/octet-stream".to_string(),
|
||||
}
|
||||
}
|
||||
|
@ -195,7 +207,7 @@ fn generate_index(directory: String) -> String {
|
|||
|
||||
}
|
||||
|
||||
fn get_page(filename: String) -> GetPageResult {
|
||||
fn get_page(filename: String, settings: Settings) -> GetPageResult {
|
||||
|
||||
// The loaded page should be left immutable as it does
|
||||
// not need to be modified by the server.
|
||||
|
@ -204,16 +216,30 @@ fn get_page(filename: String) -> GetPageResult {
|
|||
let checks = check_if_path_exists(path.clone());
|
||||
let index = check_if_dir(path.clone());
|
||||
|
||||
let mut resultstruct = GetPageResult { is500: false, is502: false, contents: vec![], iscgi: false };
|
||||
let mut resultstruct = GetPageResult { is500: false, is502: false, is403: false, contents: vec![], iscgi: false };
|
||||
|
||||
println!("{} {} {}", path, checks, index);
|
||||
|
||||
if checks == true && index == false {
|
||||
if path.contains(".") != true && path.contains(".cgi?") != true {
|
||||
let result = generate_index(filename);
|
||||
let result;
|
||||
if settings.index_generation == false {
|
||||
result = "<!DOCTYPE HTML><html><body><h1>403 Forbidden</h1><p>You do not have permission to access this resource</p></body></html>".to_string();
|
||||
resultstruct.is403 = true;
|
||||
} else {
|
||||
result = generate_index(filename);
|
||||
}
|
||||
|
||||
resultstruct.contents = result.to_string().into_bytes();
|
||||
return resultstruct;
|
||||
} else if path.contains(".cgi?") {
|
||||
} else if path.contains(".cgi?") {
|
||||
if settings.cgi == false {
|
||||
let result = "<!DOCTYPE HTML><html><body><h1>403 Forbidden</h1><p>You do not have permission to access this resource</p></body></html>".to_string();
|
||||
resultstruct.contents = result.into_bytes();
|
||||
resultstruct.is403 = true;
|
||||
return resultstruct;
|
||||
}
|
||||
|
||||
let result = process_cgi(filename);
|
||||
if result.is_some() {
|
||||
resultstruct.contents = result.unwrap();
|
||||
|
@ -228,6 +254,13 @@ fn get_page(filename: String) -> GetPageResult {
|
|||
}
|
||||
|
||||
if filename.contains(".cgi") {
|
||||
if settings.cgi == false {
|
||||
let result = "<!DOCTYPE HTML><html><body><h1>403 Forbidden</h1><p>You do not have permission to access this resource</p></body></html>".to_string();
|
||||
resultstruct.contents = result.into_bytes();
|
||||
resultstruct.is403 = true;
|
||||
return resultstruct;
|
||||
}
|
||||
|
||||
let result = process_cgi(filename);
|
||||
if result.is_some() {
|
||||
resultstruct.contents = result.unwrap();
|
||||
|
@ -252,14 +285,20 @@ fn get_page(filename: String) -> GetPageResult {
|
|||
return resultstruct;
|
||||
}
|
||||
} else {
|
||||
if filename == "index.html" {
|
||||
let newresult = generate_index(".".to_string());
|
||||
resultstruct.contents = newresult.to_string().into_bytes();
|
||||
return resultstruct;
|
||||
if filename == "index.html" {
|
||||
let newresult;
|
||||
if settings.index_generation == false {
|
||||
newresult = "<!DOCTYPE HTML><html><body><h1>403 Forbidden</h1><p>You do not have permission to access this resource</p></body></html>".to_string();
|
||||
resultstruct.is403 = true;
|
||||
} else {
|
||||
newresult = generate_index(".".to_string());
|
||||
}
|
||||
resultstruct.contents = "<!DOCTYPE HTML><html><body><h1>500 Internal Server Error</h1><p>The resource you are trying to access cannot be read by the server.</p></body></html>".to_string().into_bytes();
|
||||
resultstruct.is500 = true;
|
||||
resultstruct.contents = newresult.to_string().into_bytes();
|
||||
return resultstruct;
|
||||
}
|
||||
resultstruct.contents = "<!DOCTYPE HTML><html><body><h1>500 Internal Server Error</h1><p>The resource you are trying to access cannot be read by the server.</p></body></html>".to_string().into_bytes();
|
||||
resultstruct.is500 = true;
|
||||
return resultstruct;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -274,7 +313,7 @@ fn grab_time() -> String{
|
|||
}
|
||||
|
||||
|
||||
fn process_request(request: Vec<u8>) -> Resource {
|
||||
fn process_request(request: Vec<u8>, settings: Settings) -> Resource {
|
||||
let input = String::from_utf8_lossy(&request).to_string();
|
||||
let prerequest = construct_request(&input);
|
||||
let request;
|
||||
|
@ -317,6 +356,12 @@ fn process_request(request: Vec<u8>) -> Resource {
|
|||
cgipathraw = format!("{}/{}", cgipathraw, seg);
|
||||
}
|
||||
}
|
||||
if settings.cgi == false {
|
||||
let newcontents = "<!DOCTYPE HTML><html><body><h1>403 Forbidden</h1><p>You do not have permission to access this resource</p></body></html>".to_string().into_bytes();
|
||||
let resource = Resource { contents: newcontents, status_code: 403, mime: "text/html".to_string(), iscgi: false };
|
||||
return resource;
|
||||
}
|
||||
|
||||
let contents = process_cgi_with_path(cgipathraw, segclone, cgiscript);
|
||||
if contents.is_some() {
|
||||
let resource = Resource { contents: contents.unwrap(), status_code: 200, mime: "text/html".to_string(), iscgi: true };
|
||||
|
@ -353,7 +398,7 @@ fn process_request(request: Vec<u8>) -> Resource {
|
|||
}
|
||||
|
||||
// Did you want to see chars.as_str().to_string()?
|
||||
let rescontents = get_page(output.to_string());
|
||||
let rescontents = get_page(output.to_string(), settings.clone());
|
||||
let mut resource = Resource { contents: rescontents.contents, status_code: 200, mime: detect_media_type(output.split("?").collect::<Vec<&str>>()[0].to_string()), iscgi: false };
|
||||
if rescontents.is500 {
|
||||
resource.status_code = 500;
|
||||
|
@ -365,6 +410,11 @@ fn process_request(request: Vec<u8>) -> Resource {
|
|||
resource.mime = "text/html".to_string();
|
||||
}
|
||||
|
||||
if rescontents.is403 {
|
||||
resource.status_code = 403;
|
||||
resource.mime = "text/html".to_string();
|
||||
}
|
||||
|
||||
if rescontents.iscgi {
|
||||
resource.iscgi = true;
|
||||
}
|
||||
|
@ -373,7 +423,7 @@ fn process_request(request: Vec<u8>) -> Resource {
|
|||
|
||||
}
|
||||
|
||||
fn serve(mut stream: TcpStream) {
|
||||
fn serve(mut stream: TcpStream, settings: Settings) {
|
||||
thread::spawn(move || {
|
||||
println!("Stream thread created.");
|
||||
let mut request = Vec::new();
|
||||
|
@ -382,7 +432,7 @@ fn serve(mut stream: TcpStream) {
|
|||
.read_until(b'\n', &mut request)
|
||||
.expect("Failed to read from stream!");
|
||||
|
||||
let resource = process_request(request);
|
||||
let resource = process_request(request, settings.clone());
|
||||
|
||||
let mut response_constructed = generate_response(resource.status_code, "");
|
||||
response_constructed.headers.push(generate_kvheader("Content-Type", &resource.mime));
|
||||
|
@ -409,13 +459,45 @@ fn serve(mut stream: TcpStream) {
|
|||
});
|
||||
}
|
||||
|
||||
fn process_settings() -> Settings {
|
||||
let string = fs::read_to_string("../settings.toml");
|
||||
if string.is_err() {
|
||||
return Settings::new();
|
||||
}
|
||||
let parsed = frostwalker::parse(&string.unwrap());
|
||||
if parsed.is_err() {
|
||||
return Settings::new();
|
||||
}
|
||||
let hashmap = parsed.unwrap();
|
||||
let mut settings = Settings::new();
|
||||
if hashmap.get("cgi").is_some() {
|
||||
if hashmap.get("cgi").unwrap_or(&"".to_string()).parse::<bool>().is_ok() {
|
||||
settings.cgi = hashmap.get("cgi").unwrap_or(&"true".to_string()).parse::<bool>().unwrap_or(true);
|
||||
}
|
||||
}
|
||||
|
||||
if hashmap.get("index_generation").is_some() {
|
||||
println!("a");
|
||||
if hashmap.get("index_generation").unwrap_or(&"".to_string()).parse::<bool>().is_ok() {
|
||||
settings.index_generation = hashmap.get("index_generation").unwrap_or(&"true".to_string()).parse::<bool>().unwrap_or(true);
|
||||
println!("{}", settings.index_generation);
|
||||
}
|
||||
}
|
||||
|
||||
if hashmap.get("address").is_some() {
|
||||
settings.address = hashmap.get("address").unwrap_or(&"0.0.0.0:8080".to_string()).to_string();
|
||||
}
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
fn main() -> std::io::Result<()> {
|
||||
let listen = TcpListener::bind("0.0.0.0:8080")?;
|
||||
let settings = process_settings();
|
||||
let listen = TcpListener::bind(settings.address.clone())?;
|
||||
|
||||
for stream in listen.incoming() {
|
||||
println!("Serving incoming stream.");
|
||||
serve(stream?);
|
||||
serve(stream?, settings.clone());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue