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

```rust
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:

```sh
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:

```sh
cargo run --example hello_gemini
```

## License

MIT