mini-static 0.38.5

A secure, async static file server with streaming, traversal protection, and connection limits.
Documentation
//! A composed deployment for `bench/throughput.sh`: API routes in front, files behind.
//!
//! The configuration the layering exists to make possible, measured against the same crate
//! serving files alone. The question it answers is what the router costs the file half —
//! every file request walks the route table, misses, and falls through, so if registering
//! routes is expensive then composition is a tax on static serving rather than a feature.
//!
//! Sixteen routes rather than one: a table with a single entry would flatter the walk.

use std::env;
use std::path::Path;
use std::time::Duration;

use hyper::Response;
use mini_serve::{body, handler, RouteBuilder, ServeError};

#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let port: u16 = env::var("PORT").unwrap_or_else(|_| "8088".into()).parse()?;
    let root = env::var("ROOT").unwrap_or_else(|_| "./bench/www".into())
        ;
    let files = mini_static::Server::new(Path::new(&root))?;

    let mut builder = RouteBuilder::stateless()
        .with_header_read_timeout(Duration::from_secs(30));
    for n in 0..16 {
        let path = format!("/api/v1/resource{n}/detail");
        builder = builder.get(
            &path,
            handler(|_req, _state| async {
                Ok::<_, ServeError>(Response::new(body("api".into())))
            }),
        );
    }
    // `NO_FALLBACK=1` measures the same route table with no file fallback, which answers
    // the mirror question: does registering a fallback cost the API half anything?
    let app = if env::var("NO_FALLBACK").is_ok() {
        builder.seal()
    } else {
        builder.with_fallback(files.into_fallback()).seal()
    };

    let listener = tokio::net::TcpListener::bind(("127.0.0.1", port)).await?;
    eprintln!("composed bench server on {port}");
    app.run(listener, mini_serve::shutdown_signal()?).await?;
    Ok(())
}