0.7.0: heavily clean up CGI implementation and make it way more standards compliant and seamless with the rest of the code. fixes #5
This commit is contained in:
parent
87b79b5bd2
commit
ce9600a56f
4 changed files with 56 additions and 20 deletions
|
@ -1 +1 @@
|
||||||
6
|
7
|
||||||
|
|
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -4,7 +4,7 @@ version = 3
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "herb"
|
name = "herb"
|
||||||
version = "0.6.2"
|
version = "0.7.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"packeteer",
|
"packeteer",
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "herb"
|
name = "herb"
|
||||||
version = "0.6.2"
|
version = "0.7.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
|
||||||
|
|
66
src/main.rs
66
src/main.rs
|
@ -12,14 +12,17 @@ struct Resource {
|
||||||
contents: Vec<u8>,
|
contents: Vec<u8>,
|
||||||
status_code: i32,
|
status_code: i32,
|
||||||
mime: String,
|
mime: String,
|
||||||
|
iscgi: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct GetPageResult {
|
struct GetPageResult {
|
||||||
is500: bool,
|
is500: bool,
|
||||||
|
is502: bool,
|
||||||
contents: Vec<u8>,
|
contents: Vec<u8>,
|
||||||
|
iscgi: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_cgi(filename: String) -> String {
|
fn process_cgi(filename: String) -> Option<Vec<u8>> {
|
||||||
// This is gonna be the boggiest implementation of CGI that anyone
|
// This is gonna be the boggiest implementation of CGI that anyone
|
||||||
// has ever seen in the history of the fucking world
|
// has ever seen in the history of the fucking world
|
||||||
|
|
||||||
|
@ -44,19 +47,20 @@ fn process_cgi(filename: String) -> String {
|
||||||
.env("REQUEST_METHOD", "GET")
|
.env("REQUEST_METHOD", "GET")
|
||||||
.env("QUERY_STRING", query)
|
.env("QUERY_STRING", query)
|
||||||
.env("SCRIPT_NAME", script)
|
.env("SCRIPT_NAME", script)
|
||||||
.output()
|
.output();
|
||||||
.expect("failed to execute process");
|
|
||||||
} 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", format!("herb/{}", env!("CARGO_PKG_VERSION")))
|
.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();
|
||||||
.expect("failed to execute process");
|
}
|
||||||
|
if output.is_ok() {
|
||||||
|
return Some(output.unwrap().stdout);
|
||||||
|
} else {
|
||||||
|
return None;
|
||||||
}
|
}
|
||||||
let outputd = String::from_utf8_lossy(&output.stdout).to_string();
|
|
||||||
return outputd;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn detect_media_type(filename: String) -> String {
|
fn detect_media_type(filename: String) -> String {
|
||||||
|
@ -149,7 +153,7 @@ fn get_page(filename: String) -> GetPageResult {
|
||||||
let checks = check_if_path_exists(path.clone());
|
let checks = check_if_path_exists(path.clone());
|
||||||
let index = check_if_dir(path.clone());
|
let index = check_if_dir(path.clone());
|
||||||
|
|
||||||
let mut resultstruct = GetPageResult { is500: false, contents: vec![] };
|
let mut resultstruct = GetPageResult { is500: false, is502: false, contents: vec![], iscgi: false };
|
||||||
|
|
||||||
println!("{} {} {}", path, checks, index);
|
println!("{} {} {}", path, checks, index);
|
||||||
|
|
||||||
|
@ -160,15 +164,29 @@ fn get_page(filename: String) -> GetPageResult {
|
||||||
return resultstruct;
|
return resultstruct;
|
||||||
} else if path.contains(".cgi?") {
|
} else if path.contains(".cgi?") {
|
||||||
let result = process_cgi(filename);
|
let result = process_cgi(filename);
|
||||||
resultstruct.contents = result.to_string().into_bytes();
|
if result.is_some() {
|
||||||
|
resultstruct.contents = result.unwrap();
|
||||||
|
resultstruct.iscgi = true;
|
||||||
return resultstruct;
|
return resultstruct;
|
||||||
|
} else {
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if filename.contains(".cgi") {
|
if filename.contains(".cgi") {
|
||||||
let result = process_cgi(filename);
|
let result = process_cgi(filename);
|
||||||
resultstruct.contents = result.to_string().into_bytes();
|
if result.is_some() {
|
||||||
|
resultstruct.contents = result.unwrap();
|
||||||
|
resultstruct.iscgi = true;
|
||||||
return resultstruct;
|
return resultstruct;
|
||||||
|
} else {
|
||||||
|
resultstruct.contents = "<!DOCTYPE HTML><html><body><h1>502 Bad Gateway</h1><p>The server is unable to complete your request due to an error.</p></body></html>".to_string().into_bytes();
|
||||||
|
resultstruct.is502 = true;
|
||||||
|
return resultstruct;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
let f = File::open(filename.clone());
|
let f = File::open(filename.clone());
|
||||||
if f.is_ok() {
|
if f.is_ok() {
|
||||||
|
@ -178,8 +196,8 @@ fn get_page(filename: String) -> GetPageResult {
|
||||||
resultstruct.contents = buf;
|
resultstruct.contents = buf;
|
||||||
return resultstruct;
|
return resultstruct;
|
||||||
} else {
|
} else {
|
||||||
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.contents = "<!DOCTYPE HTML><html><body><h1>502 Bad Gateway</h1><p>The server is unable to complete your request due to an error.</p></body></html>".to_string().into_bytes();
|
||||||
resultstruct.is500 = true;
|
resultstruct.is502 = true;
|
||||||
return resultstruct;
|
return resultstruct;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -222,7 +240,7 @@ fn process_request(request: Vec<u8>) -> Resource {
|
||||||
let exists = check_if_path_exists(path.clone());
|
let exists = check_if_path_exists(path.clone());
|
||||||
|
|
||||||
if exists == false && path.contains(".cgi?") == false {
|
if exists == false && path.contains(".cgi?") == false {
|
||||||
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().into_bytes(), status_code: 404, mime: "text/html".to_string() };
|
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().into_bytes(), status_code: 404, mime: "text/html".to_string(), iscgi: false };
|
||||||
return resource;
|
return resource;
|
||||||
} else {
|
} else {
|
||||||
let dir = check_if_dir(path.clone());
|
let dir = check_if_dir(path.clone());
|
||||||
|
@ -238,18 +256,28 @@ fn process_request(request: Vec<u8>) -> Resource {
|
||||||
output = "index.html";
|
output = "index.html";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
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().into_bytes(), status_code: 501, mime: "text/html".to_string() };
|
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().into_bytes(), status_code: 501, mime: "text/html".to_string(), iscgi: false };
|
||||||
println!("Stream sent unhandlable request.");
|
println!("Stream sent unhandlable request.");
|
||||||
return resource;
|
return resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Did you want to see chars.as_str().to_string()?
|
// Did you want to see chars.as_str().to_string()?
|
||||||
let rescontents = get_page(output.to_string());
|
let rescontents = get_page(output.to_string());
|
||||||
let mut resource = Resource { contents: rescontents.contents, status_code: 200, mime: detect_media_type(output.split("?").collect::<Vec<&str>>()[0].to_string()) };
|
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 {
|
if rescontents.is500 {
|
||||||
resource.status_code = 500;
|
resource.status_code = 500;
|
||||||
resource.mime = "text/html".to_string();
|
resource.mime = "text/html".to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if rescontents.is502 {
|
||||||
|
resource.status_code = 502;
|
||||||
|
resource.mime = "text/html".to_string();
|
||||||
|
}
|
||||||
|
|
||||||
|
if rescontents.iscgi {
|
||||||
|
resource.iscgi = true;
|
||||||
|
}
|
||||||
|
|
||||||
return resource;
|
return resource;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -273,6 +301,14 @@ fn serve(mut stream: TcpStream) {
|
||||||
response_constructed.headers.push(generate_kvheader("Date", &grab_time()))
|
response_constructed.headers.push(generate_kvheader("Date", &grab_time()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if resource.iscgi {
|
||||||
|
let mut header = "HTTP/1.1 200 OK\r\n".to_string().into_bytes();
|
||||||
|
stream.write(header.as_slice()).unwrap();
|
||||||
|
stream.write(&resource.contents).unwrap();
|
||||||
|
stream.flush().unwrap();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let mut contents_clone = resource.contents.clone();
|
let mut contents_clone = resource.contents.clone();
|
||||||
let mut unpacked_response = unpack_response(response_constructed).into_bytes();
|
let mut unpacked_response = unpack_response(response_constructed).into_bytes();
|
||||||
unpacked_response.append(&mut contents_clone);
|
unpacked_response.append(&mut contents_clone);
|
||||||
|
|
Loading…
Reference in a new issue