git-gemini-forge 0.1.1

A simple Gemini server that serves a read-only view of public repositories from a Git forge.
mod config;
mod handlers;
mod network;

use config::config;
use url::Url;
use windmark::response::Response;

// TODO: Somehow ensure sure we never panic except in expected places

#[windmark::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
	let cfg: config::Config = config()?; // Panics if misconfigured
	let version: &'static str = cfg.crate_version;

	return windmark::router::Router::new()
		.set_private_key_file(format!("{}/key.pem", cfg.certs_dir))
		.set_certificate_file(format!("{}/cert.pem", cfg.certs_dir))
		.add_header(|_| String::from("# Forgejo Proxy"))
		.add_footer(move |_| format!("\nPowered by git-gemini-forge v{version}\n=> https://git.average.name/AverageHelper/git-gemini-forge View source"))
		.mount("/", move |_| {
			let c: config::Config = cfg.clone();
			async move {
				match handlers::root::handler(&c) {
					Ok(res) => res,
					Err(network::error::Error::NetworkFailure) => Response::temporary_failure("Couldn't communicate with the forge."),
					Err(network::error::Error::UnexpectedResponse(_)) => Response::temporary_failure("The forge gave us a response we don't understand"),
				}
			}
		})
		.mount("/:user", |c| {
			return async move {
				let user = c.url.path().split("/").last().unwrap_or("");
				Response::success(format!("TODO: Present repos for user {user}"))
			}
		})
		// .mount("/*", windmark::not_found!("Nothing to be found here!"))
		.set_error_handler(|error| {
			let failure_addr: Url = error.url;
			println!("Failed to serve {}", failure_addr.as_str());
			return Response::temporary_failure("Something went wrong!");
		})
		.run()
		.await

	// TODO: For a given username, get `/api/v1/users/{username}/repos`
	// TODO: For a given repo name, get `/api/v1/repos/{username}/{repo}`
	// TODO: Serve a Gemtext page: `{Owner}'s {repo.language || 'empty'} project.`
	// TODO: Interesting stuff from there
}