mini-static 0.12.5

A secure, async static file server with streaming, traversal protection, and connection limits.
Documentation
use std::fmt;

/// Errors that can occur during static file serving.
///
/// This error type is non-exhaustive and may gain new variants in future releases.
///
/// # Variants
///
/// - `NotFound`: The requested path does not exist.
/// - `Traversal`: The requested path attempts to escape the server root.
/// - `Io`: An I/O error occurred (file read, permission denied, etc.).
#[derive(Debug)]
#[non_exhaustive]
pub enum StaticError {
    /// Requested path does not exist.
    NotFound(String),
    /// Path traversal attempt detected.
    Traversal(String),
    /// I/O error from the filesystem.
    Io(std::io::Error),
}

impl fmt::Display for StaticError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            StaticError::NotFound(path) => write!(f, "not found: {path}"),
            StaticError::Traversal(path) => write!(f, "path traversal denied: {path}"),
            StaticError::Io(e) => write!(f, "io error: {e}"),
        }
    }
}

impl std::error::Error for StaticError {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        match self {
            StaticError::Io(e) => Some(e),
            _ => None,
        }
    }
}

impl StaticError {
    /// Returns a user-safe error message for use in HTTP responses.
    ///
    /// Traversal errors return "not found" to avoid leaking information about
    /// the filesystem structure. I/O errors return "internal server error".
    pub fn user_message(&self) -> String {
        match self {
            StaticError::NotFound(_) => "not found".to_string(),
            StaticError::Traversal(_) => "not found".to_string(),
            StaticError::Io(_) => "internal server error".to_string(),
        }
    }
}

impl From<std::io::Error> for StaticError {
    fn from(e: std::io::Error) -> Self {
        StaticError::Io(e)
    }
}