rework to use packeteer and fix status codes, clean up code
This commit is contained in:
parent
021b1826b6
commit
9b8eee2a23
4 changed files with 50 additions and 41 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,2 +1,3 @@
|
||||||
/target
|
/target
|
||||||
/src/content
|
/src/content
|
||||||
|
index.html
|
||||||
|
|
9
Cargo.lock
generated
9
Cargo.lock
generated
|
@ -5,3 +5,12 @@ version = 3
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "herb"
|
name = "herb"
|
||||||
version = "0.4.2"
|
version = "0.4.2"
|
||||||
|
dependencies = [
|
||||||
|
"packeteer",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "packeteer"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "582fc2c3395c690f0d079658b1acc23848b294f5a0753c54675011f09a0ec815"
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
[package]
|
[package]
|
||||||
name = "herb"
|
name = "herb"
|
||||||
version = "0.4.2"
|
version = "0.5.0"
|
||||||
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
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
packeteer = { version = "0.5.1", features = ["http1"] }
|
||||||
|
|
78
src/main.rs
78
src/main.rs
|
@ -4,6 +4,14 @@ use std::net::{TcpListener, TcpStream};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::string::{String};
|
use std::string::{String};
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
use packeteer::http1::*;
|
||||||
|
use packeteer::generate_kvheader;
|
||||||
|
|
||||||
|
struct Resource {
|
||||||
|
contents: String,
|
||||||
|
status_code: i32,
|
||||||
|
mime: String,
|
||||||
|
}
|
||||||
|
|
||||||
fn process_cgi(filename: String) -> String {
|
fn process_cgi(filename: String) -> String {
|
||||||
// This is gonna be the boggiest implementation of CGI that anyone
|
// This is gonna be the boggiest implementation of CGI that anyone
|
||||||
|
@ -27,7 +35,7 @@ fn process_cgi(filename: String) -> String {
|
||||||
if query != "" {
|
if query != "" {
|
||||||
output = Command::new(format!("./{}", script))
|
output = Command::new(format!("./{}", script))
|
||||||
.env("GATEWAY_INTERFACE", "CGI/1.1")
|
.env("GATEWAY_INTERFACE", "CGI/1.1")
|
||||||
.env("SERVER_SOFTWARE", "Herb/0.4.2")
|
.env("SERVER_SOFTWARE", format!("herb/{}", env!("CARGO_PKG_VERSION")))
|
||||||
.env("REQUEST_METHOD", "GET")
|
.env("REQUEST_METHOD", "GET")
|
||||||
.env("QUERY_STRING", query)
|
.env("QUERY_STRING", query)
|
||||||
.env("SCRIPT_NAME", script)
|
.env("SCRIPT_NAME", script)
|
||||||
|
@ -36,7 +44,7 @@ fn process_cgi(filename: String) -> String {
|
||||||
} else {
|
} else {
|
||||||
output = Command::new(format!("./{}", script))
|
output = Command::new(format!("./{}", script))
|
||||||
.env("GATEWAY_INTERFACE", "CGI/1.1")
|
.env("GATEWAY_INTERFACE", "CGI/1.1")
|
||||||
.env("SERVER_SOFTWARE", "Herb/0.4.2")
|
.env("SERVER_SOFTWARE", format!("herb/{}", env!("CARGO_PKG_VERSION")))
|
||||||
.env("REQUEST_METHOD", "GET")
|
.env("REQUEST_METHOD", "GET")
|
||||||
.env("SCRIPT_NAME", script)
|
.env("SCRIPT_NAME", script)
|
||||||
.output()
|
.output()
|
||||||
|
@ -91,7 +99,7 @@ fn detect_media_type(filename: String) -> String {
|
||||||
"htm" => "text/html".to_string(),
|
"htm" => "text/html".to_string(),
|
||||||
"cgi" => "text/html".to_string(),
|
"cgi" => "text/html".to_string(),
|
||||||
".error_server_404" => "text/html".to_string(),
|
".error_server_404" => "text/html".to_string(),
|
||||||
".error_server_503" => "text/html".to_string(),
|
".error_server_501" => "text/html".to_string(),
|
||||||
_ => "application/octet-stream".to_string(),
|
_ => "application/octet-stream".to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -126,7 +134,7 @@ fn generate_index(directory: String) -> String {
|
||||||
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, format!("\"./{}\"", file.as_ref().unwrap().path().display().to_string()), file.unwrap().file_name());
|
||||||
}
|
}
|
||||||
|
|
||||||
return format!("{}<hr/>Generated by herb 0.4.2", index).to_string();
|
return format!("{}<hr/>Generated by herb {}", index, env!("CARGO_PKG_VERSION")).to_string();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,10 +144,8 @@ fn get_page(filename: String) -> String {
|
||||||
// not need to be modified by the server.
|
// not need to be modified by the server.
|
||||||
|
|
||||||
let path = filename.to_string();
|
let path = filename.to_string();
|
||||||
let checks = check_if_path_exists(path);
|
let checks = check_if_path_exists(path.clone());
|
||||||
let path = filename.to_string();
|
let index = check_if_dir(path.clone());
|
||||||
let index = check_if_dir(path);
|
|
||||||
let path = filename.to_string();
|
|
||||||
|
|
||||||
println!("{} {} {}", path, checks, index);
|
println!("{} {} {}", path, checks, index);
|
||||||
|
|
||||||
|
@ -153,13 +159,7 @@ fn get_page(filename: String) -> String {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if filename == ".error_server_404" {
|
if filename.contains(".cgi") {
|
||||||
let result = "<!DOCTYPE HTML><html><body><h1>404 Not Found</h1><p>The resource you are trying to locate cannot be accessed!</p></body></html>";
|
|
||||||
return result.to_string();
|
|
||||||
} else if filename == ".error_server_503" {
|
|
||||||
let result = "<!DOCTYPE HTML><html><body><h1>503 Not Implemented</h1><p>The request sent by your web browser cannot be handled by this server software.</p></body></html>";
|
|
||||||
return result.to_string();
|
|
||||||
} else if filename.contains(".cgi") {
|
|
||||||
let result = process_cgi(filename);
|
let result = process_cgi(filename);
|
||||||
return result.to_string();
|
return result.to_string();
|
||||||
} else {
|
} else {
|
||||||
|
@ -178,11 +178,11 @@ fn grab_time() -> String{
|
||||||
.output()
|
.output()
|
||||||
.expect("failed to execute process");
|
.expect("failed to execute process");
|
||||||
|
|
||||||
return String::from_utf8_lossy(&output.stdout).to_string();
|
return String::from_utf8_lossy(&output.stdout).to_string().replace("'","").replace("\n","");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn process_request(request: Vec<u8>) -> String {
|
fn process_request(request: Vec<u8>) -> Resource {
|
||||||
let mut input = String::from_utf8_lossy(&request).to_string();
|
let mut input = String::from_utf8_lossy(&request).to_string();
|
||||||
|
|
||||||
let debug = false;
|
let debug = false;
|
||||||
|
@ -215,7 +215,8 @@ fn process_request(request: Vec<u8>) -> String {
|
||||||
let path = chars.as_str().to_string();
|
let path = chars.as_str().to_string();
|
||||||
|
|
||||||
if exists == false && path.contains(".cgi?") == false {
|
if exists == false && path.contains(".cgi?") == false {
|
||||||
output = ".error_server_404";
|
let resource = Resource { contents: "<!DOCTYPE HTML><html><body><h1>404 Not Found</h1><p>The resource you are trying to locate cannot be accessed!</p></body></html>".to_string(), status_code: 404, mime: "text/html".to_string() };
|
||||||
|
return resource;
|
||||||
} else {
|
} else {
|
||||||
let path = chars.as_str().to_string();
|
let path = chars.as_str().to_string();
|
||||||
let dir = check_if_dir(path);
|
let dir = check_if_dir(path);
|
||||||
|
@ -235,12 +236,18 @@ fn process_request(request: Vec<u8>) -> String {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// It's get_page()'s problem now.
|
// It's get_page()'s problem now.
|
||||||
|
let resource = Resource { contents: "<!DOCTYPE HTML><html><body><h1>501 Not Implemented</h1><p>The request sent by your web browser cannot be handled by this server software.</p></body></html>".to_string(), status_code: 501, mime: "text/html".to_string() };
|
||||||
println!("Stream sent unhandlable request.");
|
println!("Stream sent unhandlable request.");
|
||||||
output = ".error_server_503";
|
return resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Did you want to see chars.as_str().to_string()?
|
// Did you want to see chars.as_str().to_string()?
|
||||||
return output.to_string();
|
let mut resource = Resource { contents: get_page(output.to_string()), status_code: 200, mime: detect_media_type(output.to_string()) };
|
||||||
|
if resource.contents.contains("500 Internal Server Error") {
|
||||||
|
resource.status_code = 500;
|
||||||
|
resource.mime = "text/html".to_string();
|
||||||
|
}
|
||||||
|
return resource;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,34 +262,25 @@ fn serve(mut stream: TcpStream) {
|
||||||
|
|
||||||
let resource = process_request(request);
|
let resource = process_request(request);
|
||||||
|
|
||||||
// Haha, bodged my way around Rust's ownership paradigm!
|
// let contents = get_page(resource.clone());
|
||||||
let mime;
|
// let header = "HTTP/1.1 200 OK\r\n";
|
||||||
|
// let content_type = format!("Content-Type: {}\r\n", mime);
|
||||||
|
// let server = format!("Server: herb/{}\r\n", env!("CARGO_PKG_VERSION"));
|
||||||
|
// let extra_fields;
|
||||||
|
|
||||||
if resource.to_string().contains(".error") {
|
let mut response_constructed = generate_response(resource.status_code, &resource.contents);
|
||||||
mime = "text/html".to_string();
|
response_constructed.headers.push(generate_kvheader("Content-Type", &resource.mime));
|
||||||
} else {
|
response_constructed.headers.push(generate_kvheader("Server", &format!("herb/{}", env!("CARGO_PKG_VERSION"))));
|
||||||
mime = detect_media_type(resource.to_string());
|
|
||||||
}
|
|
||||||
let contents = get_page(resource);
|
|
||||||
let header = "HTTP/1.1 200 OK\r\n";
|
|
||||||
let content_type = format!("Content-Type: {}\r\n", mime);
|
|
||||||
let server = "Server: Herb/0.4.2\r\n";
|
|
||||||
let extra_fields;
|
|
||||||
|
|
||||||
if cfg!(unix) {
|
if cfg!(unix) {
|
||||||
let mut time = format!("Date: {}\r\n", grab_time());
|
response_constructed.headers.push(generate_kvheader("Date", &grab_time()))
|
||||||
time = time.replace("'","");
|
|
||||||
extra_fields = format!("{}{}\r\n", server, time);
|
|
||||||
} else {
|
} else {
|
||||||
// I don't have a Windows or macOS box to test anything on
|
// I don't have a Windows or macOS box to test anything on
|
||||||
// which means others are gonna have to deal with it :/
|
// which means others are gonna have to deal with it :/
|
||||||
|
|
||||||
extra_fields = format!("{}\r\n", server);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let response = format!("{}{}{}{}", header, content_type, extra_fields, contents);
|
println!("{:#?}", response_constructed);
|
||||||
|
stream.write(unpack_response(response_constructed).as_bytes()).unwrap();
|
||||||
stream.write(response.as_bytes()).unwrap();
|
|
||||||
stream.flush().unwrap();
|
stream.flush().unwrap();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue