about summary refs log tree commit diff
diff options
context:
space:
mode:
authorgennyble <gen@nyble.dev>2025-03-11 16:34:13 -0500
committergennyble <gen@nyble.dev>2025-03-11 16:34:13 -0500
commita3798984ad4d77ae66d28478a19fb3e50e7a64f7 (patch)
treefc141dfd17aa86028e02f1e51575f295a2a3954f
parent912ce0966c42f126d7a37c88e442e16a30308415 (diff)
downloadcorgi-a3798984ad4d77ae66d28478a19fb3e50e7a64f7.tar.gz
corgi-a3798984ad4d77ae66d28478a19fb3e50e7a64f7.zip
allow setting script path to execute
-rw-r--r--Cargo.lock7
-rw-r--r--Cargo.toml1
-rw-r--r--README.md3
-rw-r--r--TODO.md8
-rw-r--r--corgi.conf1
-rw-r--r--src/main.rs39
6 files changed, 51 insertions, 8 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 55b19f3..25241c8 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -45,9 +45,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
+name = "confindent"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c5a06ecfd8e0b653f5b0a1b083f74a275d2aab7834b90bce8c66f3c0b2f53fb1"
+
+[[package]]
 name = "corgi"
 version = "0.1.0"
 dependencies = [
+ "confindent",
  "http-body-util",
  "hyper",
  "hyper-util",
diff --git a/Cargo.toml b/Cargo.toml
index 206071d..77232e3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -4,6 +4,7 @@ version = "0.1.0"
 edition = "2024"
 
 [dependencies]
+confindent = "2.2.0"
 http-body-util = "0.1.3"
 hyper-util = { version = "0.1.10", features = ["tokio"] }
 
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..152c6b7
--- /dev/null
+++ b/README.md
@@ -0,0 +1,3 @@
+corgi is a CGI server.
+
+currently, it can handle on application.
\ No newline at end of file
diff --git a/TODO.md b/TODO.md
new file mode 100644
index 0000000..862bb82
--- /dev/null
+++ b/TODO.md
@@ -0,0 +1,8 @@
+(1) Support Multiple CGI Scripts
+	This is needed even just for the cgit and git server target.
+	We need to be able to support the cgit executable itself, and
+	also git-http-backend for smart clones.
+
+(2) Support Matching CGI Based On Path
+	The other requirement for git-http-backend, which needs to
+	trigger on the regex `/.+/(info/refs|git-upload-pack)`
\ No newline at end of file
diff --git a/corgi.conf b/corgi.conf
new file mode 100644
index 0000000..065d9ea
--- /dev/null
+++ b/corgi.conf
@@ -0,0 +1 @@
+Script /usr/lib/cgit/cgit.cgi
\ No newline at end of file
diff --git a/src/main.rs b/src/main.rs
index 72abb0e..e0f20a1 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,6 +1,7 @@
 use core::panic;
 use std::{net::SocketAddr, pin::Pin};
 
+use confindent::Confindent;
 use http_body_util::{BodyExt, Full};
 use hyper::{
 	Request, Response, StatusCode,
@@ -11,16 +12,33 @@ use hyper::{
 use hyper_util::rt::TokioIo;
 use tokio::{net::TcpListener, process::Command, runtime::Runtime};
 
+#[derive(Clone, Debug)]
+pub struct Settings {
+	script_filename: String,
+	env: Vec<(String, String)>,
+}
+
+const CONF_DEFAULT: &str = "/etc/corgi.conf";
+
 fn main() {
+	let conf_path = std::env::args().nth(1).unwrap_or(String::from(CONF_DEFAULT));
+	let conf = Confindent::from_file(conf_path).expect("failed to open conf");
+
+	let script = conf.child("Script").expect("no 'Script' key in conf");
+	let settings = Settings {
+		script_filename: script.value_owned().expect("'Script' key has no value'"),
+		env: vec![],
+	};
+
 	let rt = Runtime::new().unwrap();
-	rt.block_on(async { run().await });
+	rt.block_on(async { run(settings).await });
 }
 
-async fn run() {
+async fn run(settings: Settings) {
 	let addr = SocketAddr::from(([0, 0, 0, 0], 2562));
 	let listen = TcpListener::bind(addr).await.unwrap();
 
-	let svc = Svc {};
+	let svc = Svc { settings };
 
 	loop {
 		let (stream, _caddr) = listen.accept().await.unwrap();
@@ -33,7 +51,9 @@ async fn run() {
 }
 
 #[derive(Clone, Debug)]
-struct Svc {}
+struct Svc {
+	settings: Settings,
+}
 
 impl Service<Request<Incoming>> for Svc {
 	type Response = Response<Full<Bytes>>;
@@ -45,20 +65,23 @@ impl Service<Request<Incoming>> for Svc {
 			Ok(Response::builder().body(Full::new(b.into())).unwrap())
 		}
 
-		Box::pin(async { Ok(Self::handle(req).await) })
+		let settings = self.settings.clone();
+		Box::pin(async { Ok(Self::handle(settings, req).await) })
 	}
 }
 
 impl Svc {
-	async fn handle(req: Request<Incoming>) -> Response<Full<Bytes>> {
+	async fn handle(settings: Settings, req: Request<Incoming>) -> Response<Full<Bytes>> {
 		let method = req.method().as_str().to_ascii_uppercase();
 		let path = req.uri().path().to_owned();
 		let headers = req.headers().clone();
 		let body = req.into_body().collect().await.unwrap().to_bytes();
 		let content_length = body.len();
 
-		let mut cmd = Command::new("/usr/lib/cgit/cgit.cgi");
-		cmd.env("PATH_INFO", path).env("REQUEST_METHOD", method);
+		let mut cmd = Command::new(&settings.script_filename);
+		cmd.env("SCRIPT_NAME", settings.script_filename)
+			.env("PATH_INFO", path)
+			.env("REQUEST_METHOD", method);
 
 		for (header, value) in headers {
 			if let Some(header) = header {