Compare commits

..

5 commits

6 changed files with 60 additions and 69 deletions

2
Cargo.lock generated
View file

@ -4,4 +4,4 @@ version = 3
[[package]] [[package]]
name = "herb" name = "herb"
version = "0.3.0" version = "0.4.2"

View file

@ -1,6 +1,6 @@
[package] [package]
name = "herb" name = "herb"
version = "0.3.0" version = "0.4.2"
edition = "2018" edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

17
README Normal file
View file

@ -0,0 +1,17 @@
herb
---------
T(h)e hackabl(e) web se(r)ver (b)inary (Formerly the web server yer mom uses.)
In all seriousness!
------------------------
This was a little fun experiment for me to mess around with Rust but at this point it has turned into a hobby server that I whittle away at.
At this point, if it's put behind a reverse proxy like HAProxy or nginx, it could actually be used as a small web server.
To-do list
---------------
Custom error pages
Make it user configurable
Properly generate headers
Image thumbnailing/compression
Compressing big files

16
README.html Normal file
View file

@ -0,0 +1,16 @@
<h2>herb</h2>
<p>T(h)e hackabl(e) web se(r)ver (b)inary (Formerly the web server yer mom uses.)</p>
<h2>In all seriousness!</h2>
<p>This was a little fun experiment for me to mess around with Rust but at this point it has turned into a hobby server that I whittle away at.</p>
<p>At this point, if it's put behind a reverse proxy like HAProxy or nginx, it could actually be used as a small web server.</p>
<h2>To-do list</h2>
<ul>
<li>Custom error pages</li>
<li>Make it user configurable</li>
<li>Properly generate headers</li>
<li>Image thumbnailing/compression</li>
<li>Compressing big files</li>
</ul>

View file

@ -1,50 +0,0 @@
# herb
The web server yer mom uses.
## In all seriousness!
This is a little fun experiment for me to mess around with Rust
## Chonklist
I need this stuff to actually have a functioning but basic web server.
[x] Open a socket
[x] Recieve HTTP requests
[x] Process said requests
[x] Send back HTTP requests
[x] Read index page from filesystem
### Next Chonklist
The stuff I need to make it usable.
[x] Read the stream
[x] Detect which resource the client wants to access
[x] Detect missing files and return a 404 page
[ ] Custom error pages
[ ] Make it user configurable
[ ] Properly generate headers
[x] Read and serve other pages from filesystem
### SUPAR Chonklist
Whatever is on here, just to make it extra spicy.
[ ] HTTPS support
[ ] HTTP/2 support
[ ] Dynamic pages via CGI?
[ ] Image thumbnailing/compression
[ ] Compressing big files
[x] Directory index generation

View file

@ -21,16 +21,27 @@ fn process_cgi(filename: String) -> String {
query = ""; query = "";
script = &filename; script = &filename;
} }
println!("{}", script);
let output;
let output = Command::new(script) if query != "" {
.arg("GATEWAY_INTERFACE=\"CGI/1.1\"") output = Command::new(format!("./{}", script))
.arg("SERVER_SOFTWARE=\"Herb/0.3.0\"") .env("GATEWAY_INTERFACE", "CGI/1.1")
.arg("REQUEST_METHOD=\"GET\"") .env("SERVER_SOFTWARE", "Herb/0.4.2")
.arg(format!("QUERY_STRING=\"{}\"", query)) .env("REQUEST_METHOD", "GET")
.arg(format!("SCRIPT_NAME=\"{}\"", script)) .env("QUERY_STRING", query)
.env("SCRIPT_NAME", script)
.output() .output()
.expect("failed to execute process"); .expect("failed to execute process");
} else {
output = Command::new(format!("./{}", script))
.env("GATEWAY_INTERFACE", "CGI/1.1")
.env("SERVER_SOFTWARE", "Herb/0.4.2")
.env("REQUEST_METHOD", "GET")
.env("SCRIPT_NAME", script)
.output()
.expect("failed to execute process");
}
let outputd = String::from_utf8_lossy(&output.stdout).to_string(); let outputd = String::from_utf8_lossy(&output.stdout).to_string();
return outputd; return outputd;
} }
@ -110,14 +121,12 @@ fn check_if_dir(directory: String) -> bool {
fn generate_index(directory: String) -> String { fn generate_index(directory: String) -> String {
let mut index = format!("<!DOCTYPE HTML><html><body><h1>Directory of {}</h1>", directory); let mut index = format!("<!DOCTYPE HTML><html><body><h1>Directory of {}</h1><hr/>", directory);
for file in fs::read_dir(directory).unwrap() { for file in fs::read_dir(directory).unwrap() {
index = format!("{}<br/><a href={}>{:#?}</a>", index, format!("\"./{}\"", file.as_ref().unwrap().path().display().to_string()), file.unwrap().file_name());
index = format!("{}<br/><a href={}>{:#?}</a>", index, file.as_ref().unwrap().path().display(), file.unwrap().file_name());
} }
return index.to_string(); return format!("{}<hr/>Generated by herb 0.4.2", index).to_string();
} }
@ -157,7 +166,7 @@ fn get_page(filename: String) -> String {
let result = fs::read_to_string(filename); let result = fs::read_to_string(filename);
match result { match result {
Ok(i) => i.to_string(), Ok(i) => i.to_string(),
Err(_e) => "<!DOCTYPE HTML><html><body><h1>403 Forbidden</h1><p>The resource you are trying to access cannot be read by the server.</p></body></html>".to_string(), Err(_e) => "<!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(),
} }
} }
@ -244,7 +253,6 @@ fn serve(mut stream: TcpStream) {
.read_until(b'\n', &mut request) .read_until(b'\n', &mut request)
.expect("Failed to read from stream!"); .expect("Failed to read from stream!");
let resource = process_request(request); let resource = process_request(request);
// Haha, bodged my way around Rust's ownership paradigm! // Haha, bodged my way around Rust's ownership paradigm!
@ -258,7 +266,7 @@ fn serve(mut stream: TcpStream) {
let contents = get_page(resource); let contents = get_page(resource);
let header = "HTTP/1.1 200 OK\r\n"; let header = "HTTP/1.1 200 OK\r\n";
let content_type = format!("Content-Type: {}\r\n", mime); let content_type = format!("Content-Type: {}\r\n", mime);
let server = "Server: Herb/0.3.0\r\n"; let server = "Server: Herb/0.4.2\r\n";
let extra_fields; let extra_fields;
if cfg!(unix) { if cfg!(unix) {