Fix Gemini protocol status codes and error handling

- Path security violations now return 51 (Not Found) instead of 59 (Bad Request)
- Timeouts return 41 (Server Unavailable) per Gemini spec
- Add comprehensive request validation: empty requests, oversized requests (>1024 bytes), malformed URLs
- Fix CLI argument conflict (config -c vs cert -c)
- Update documentation with status codes, error handling guidelines, and lint checking
- Add environment setup instructions for clippy and cargo PATH
This commit is contained in:
Jeena 2026-01-16 00:17:34 +00:00
parent 2347c04211
commit 9d29321806
5 changed files with 166 additions and 62 deletions

View file

@ -12,13 +12,25 @@ use tokio::net::TcpListener;
use tokio_rustls::TlsAcceptor;
use logging::init_logging;
fn print_startup_info(host: &str, port: u16, root: &str, cert: &str, key: &str, log_level: Option<&str>) {
println!("Pollux Gemini Server");
println!("Listening on: {}:{}", host, port);
println!("Serving: {}", root);
println!("Certificate: {}", cert);
println!("Key: {}", key);
if let Some(level) = log_level {
println!("Log level: {}", level);
}
println!(); // Add spacing before connections start
}
#[derive(Parser)]
#[command(author, version, about, long_about = None)]
struct Args {
/// Path to config file
#[arg(short, long)]
#[arg(short = 'C', long)]
config: Option<String>,
/// Directory to serve files from
@ -65,8 +77,8 @@ async fn main() {
// Merge config with args (args take precedence)
let root = args.root.or(config.root).expect("root is required");
let cert = args.cert.or(config.cert).expect("cert is required");
let key = args.key.or(config.key).expect("key is required");
let cert_path = args.cert.or(config.cert).expect("cert is required");
let key_path = args.key.or(config.key).expect("key is required");
let host = args.host.or(config.host).unwrap_or_else(|| "0.0.0.0".to_string());
let port = args.port.or(config.port).unwrap_or(1965);
@ -78,8 +90,8 @@ async fn main() {
}
// Load TLS certificates
let certs = tls::load_certs(&cert).unwrap();
let key = tls::load_private_key(&key).unwrap();
let certs = tls::load_certs(&cert_path).unwrap();
let key = tls::load_private_key(&key_path).unwrap();
let config = ServerConfig::builder()
.with_safe_defaults()
@ -89,13 +101,15 @@ async fn main() {
let acceptor = TlsAcceptor::from(Arc::new(config));
let listener = TcpListener::bind(format!("{}:{}", host, port)).await.unwrap();
println!("Server listening on {}:{}", host, port);
// Print startup information
print_startup_info(&host, port, &root, &cert_path, &key_path, Some(log_level));
loop {
let (stream, _) = listener.accept().await.unwrap();
let acceptor = acceptor.clone();
let dir = root.clone();
let expected_host = host.clone();
let expected_host = "localhost".to_string(); // Override for testing
if let Ok(stream) = acceptor.accept(stream).await {
if let Err(e) = server::handle_connection(stream, &dir, &expected_host).await {
tracing::error!("Error handling connection: {}", e);