gemi 0.1.0

A lightweight async Gemini protocol server framework
Documentation

gemi

A lightweight async Gemini protocol server framework built on Tokio and Rustls.

  • Async handler functions with automatic argument extraction
  • URL parameter routing with wildcards and sub-routers
  • Shared application state via extractors
  • TLS client certificate authentication
  • Composable middleware (closures and traits)
  • Built-in request tracing
  • Static file serving with directory listings
  • Gemtext document builder
  • Graceful shutdown support

Quick Start

use gemi::{EndpointExt, GeminiConfig, GeminiResponse, GeminiRouter, GeminiServer};

#[tokio::main]
async fn main() {
    let mut router = GeminiRouter::default();
    router.add_route("/", hello).unwrap();
    let app = router.with_state(());

    let server = GeminiServer::new(app, "certs/cert.der", "certs/key.der",
        GeminiConfig::new("localhost")).unwrap();

    server.serve().await.unwrap();
}

async fn hello() -> impl Into<GeminiResponse> {
    "Hello, Gemini!"
}

TLS Certificates

Gemini requires TLS. Generate a self-signed certificate for development:

mkdir -p certs
openssl genpkey -algorithm ed25519 -outform DER -out certs/key.der
openssl req -new -x509 -key certs/key.der -keyform DER \
    -out certs/cert.der -outform DER \
    -days 3650 -subj '/CN=localhost'

PKCS#1 (RSA), PKCS#8, and SEC1 (EC) key formats are all supported.

Examples

The examples/ directory covers routing, shared state, input prompts, middleware, static file serving, client certificate auth, graceful shutdown, and tracing. Run any of them with:

cargo run --example hello_gemini

License

MIT