Skip to main content

mini_static/
error.rs

1use std::fmt;
2
3/// Errors that can occur during static file serving.
4///
5/// This error type is non-exhaustive and may gain new variants in future releases.
6///
7/// # Variants
8///
9/// - `NotFound`: The requested path does not exist.
10/// - `Traversal`: The requested path attempts to escape the server root.
11/// - `Io`: An I/O error occurred (file read, permission denied, etc.).
12#[derive(Debug)]
13#[non_exhaustive]
14pub enum StaticError {
15    /// Requested path does not exist.
16    NotFound(String),
17    /// Path traversal attempt detected.
18    Traversal(String),
19    /// I/O error from the filesystem.
20    Io(std::io::Error),
21}
22
23impl fmt::Display for StaticError {
24    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25        match self {
26            StaticError::NotFound(path) => write!(f, "not found: {path}"),
27            StaticError::Traversal(path) => write!(f, "path traversal denied: {path}"),
28            StaticError::Io(e) => write!(f, "io error: {e}"),
29        }
30    }
31}
32
33impl std::error::Error for StaticError {
34    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
35        match self {
36            StaticError::Io(e) => Some(e),
37            _ => None,
38        }
39    }
40}
41
42impl StaticError {
43    /// Returns a user-safe error message for use in HTTP responses.
44    ///
45    /// Traversal errors return "not found" to avoid leaking information about
46    /// the filesystem structure. I/O errors return "internal server error".
47    pub fn user_message(&self) -> String {
48        match self {
49            StaticError::NotFound(_) => "not found".to_string(),
50            StaticError::Traversal(_) => "not found".to_string(),
51            StaticError::Io(_) => "internal server error".to_string(),
52        }
53    }
54}
55
56impl From<std::io::Error> for StaticError {
57    fn from(e: std::io::Error) -> Self {
58        StaticError::Io(e)
59    }
60}