0.7.2: Finish off CGI hopefully and add path resolving for PATH_STRING env
This commit is contained in:
parent
1656697a7c
commit
3fe3587236
5 changed files with 91 additions and 3 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -4,7 +4,7 @@ version = 3
|
|||
|
||||
[[package]]
|
||||
name = "herb"
|
||||
version = "0.7.1"
|
||||
version = "0.7.2"
|
||||
dependencies = [
|
||||
"packeteer",
|
||||
]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "herb"
|
||||
version = "0.7.1"
|
||||
version = "0.7.2"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
|
|
|
@ -11,5 +11,8 @@ herb is able to send all types of data to clients, including text, video, audio,
|
|||
* Supports text and raw data, including PNGs and MP3s
|
||||
* Installable with curze
|
||||
|
||||
## Can herb run established CGI applications?
|
||||
As of 0.7.2, herb's CGI implementation is fairly compliant and works with query strings _and_ paths. [Here's a screenshot of Cgit running under herb 0.7.2 displaying its own source code!](https://git.colean.cc/threeoh6000/herb/src/branch/master/cgit.png)
|
||||
|
||||
## Licensing
|
||||
herb is licensed under [GNU General Public License version 3.](https://git.colean.cc/threeoh6000/herb/src/branch/master/LICENSE)
|
||||
|
|
BIN
cgit.png
Normal file
BIN
cgit.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 160 KiB |
87
src/main.rs
87
src/main.rs
|
@ -6,7 +6,7 @@ use std::fs::File;
|
|||
use std::string::{String};
|
||||
use std::process::Command;
|
||||
use packeteer::http1::*;
|
||||
use packeteer::{generate_kvheader, unwrap_url_into_segments};
|
||||
use packeteer::{generate_kvheader, unwrap_url_into_segments, Url};
|
||||
|
||||
struct Resource {
|
||||
contents: Vec<u8>,
|
||||
|
@ -63,6 +63,58 @@ fn process_cgi(filename: String) -> Option<Vec<u8>> {
|
|||
}
|
||||
}
|
||||
|
||||
fn process_cgi_with_path(filename: String, segments: Vec<String>, location: i32) -> Option<Vec<u8>> {
|
||||
let query: String;
|
||||
let script = filename;
|
||||
|
||||
if segments[segments.len()-1].contains("?") {
|
||||
let vars = segments[segments.len()-1].to_string().find("?").unwrap();
|
||||
query = segments[segments.len()-1][vars..].to_string();
|
||||
} else {
|
||||
query = "".to_string();
|
||||
}
|
||||
|
||||
let mut i = 0;
|
||||
let mut path = "".to_string();
|
||||
for seg in segments {
|
||||
if !(i <= location) {
|
||||
if path == "".to_string() {
|
||||
path = format!("/{}", seg);
|
||||
} else {
|
||||
path = format!("{}/{}", path, seg);
|
||||
}
|
||||
}
|
||||
i = i + 1;
|
||||
}
|
||||
|
||||
path = format!("{}/", path);
|
||||
|
||||
let output;
|
||||
if query != "".to_string() {
|
||||
output = Command::new(format!("./{}", script))
|
||||
.env("GATEWAY_INTERFACE", "CGI/1.1")
|
||||
.env("SERVER_SOFTWARE", format!("herb/{}", env!("CARGO_PKG_VERSION")))
|
||||
.env("REQUEST_METHOD", "GET")
|
||||
.env("QUERY_STRING", query)
|
||||
.env("PATH_INFO", path)
|
||||
.env("SCRIPT_NAME", script)
|
||||
.output();
|
||||
} else {
|
||||
output = Command::new(format!("./{}", script))
|
||||
.env("GATEWAY_INTERFACE", "CGI/1.1")
|
||||
.env("SERVER_SOFTWARE", format!("herb/{}", env!("CARGO_PKG_VERSION")))
|
||||
.env("REQUEST_METHOD", "GET")
|
||||
.env("PATH_INFO", path)
|
||||
.env("SCRIPT_NAME", script)
|
||||
.output();
|
||||
}
|
||||
if output.is_ok() {
|
||||
return Some(output.unwrap().stdout);
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
fn detect_media_type(filename: String) -> String {
|
||||
|
||||
// The Lynx terminal browser made me do this.
|
||||
|
@ -242,7 +294,40 @@ fn process_request(request: Vec<u8>) -> Resource {
|
|||
println!("Stream sent GET request.");
|
||||
|
||||
if request.location.segments.len() != 0 {
|
||||
let segclone = request.location.segments.clone();
|
||||
path = unwrap_url_into_segments(request.location);
|
||||
if path.contains(".cgi/") {
|
||||
let mut cgiscript = 0;
|
||||
let mut i = 0;
|
||||
let mut cgipath: Vec<String> = vec![];
|
||||
for segment in &segclone {
|
||||
if segment.contains(".cgi") {
|
||||
cgipath.push(segment.to_string());
|
||||
cgiscript = i;
|
||||
break;
|
||||
} else {
|
||||
cgipath.push(segment.to_string());
|
||||
i = i + 1;
|
||||
}
|
||||
}
|
||||
let mut cgipathraw = "".to_string();
|
||||
for seg in cgipath {
|
||||
if cgipathraw == "".to_string() {
|
||||
cgipathraw = seg;
|
||||
} else {
|
||||
cgipathraw = format!("{}/{}", cgipathraw, seg);
|
||||
}
|
||||
}
|
||||
let contents = process_cgi_with_path(cgipathraw, segclone, cgiscript);
|
||||
if contents.is_some() {
|
||||
let mut resource = Resource { contents: contents.unwrap(), status_code: 200, mime: "text/html".to_string(), iscgi: true };
|
||||
return resource;
|
||||
} else {
|
||||
let newcontents = "<!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();
|
||||
let mut resource = Resource { contents: newcontents, status_code: 502, mime: "text/html".to_string(), iscgi: false };
|
||||
return resource;
|
||||
}
|
||||
}
|
||||
path.remove(0);
|
||||
let exists = check_if_path_exists(path.clone());
|
||||
|
||||
|
|
Loading…
Reference in a new issue