kellnr-docs 7.2.0

Kellnr is a self-hosted registry for Rust crates with support for rustdocs and crates.io caching.
Documentation
use hyper::StatusCode;
use kellnr_http::error::ApiError;
use kellnr_storage::storage_error::StorageError;
use thiserror::Error;

#[derive(Error, Debug)]
pub enum DocsError {
    #[error("Failed to extract docs")]
    ExtractFailed,
    #[error("Crate with version does not exist: {0}-{1}")]
    CrateDoesNotExist(String, String),
    #[error("Database error: {0}")]
    DatabaseError(#[from] kellnr_db::error::DbError),
    #[error("IO error: {0}")]
    IoError(#[from] std::io::Error),
    #[error("Cargo error: {0}")]
    CargoError(String),
    #[error("Docs storage error: {0}")]
    StorageError(#[from] StorageError),
    #[error("Archive exceeds the maximum uncompressed size or number of entries")]
    ArchiveTooLarge,
    #[error("Docs build timed out after {0} seconds")]
    BuildTimeout(u64),
    #[error("Docs build stopped on shutdown")]
    BuildStopped,
    #[error("Path {path} is not inside {root}")]
    PathPrefixMismatch { path: String, root: String },
    #[error("Failed to extract bytes from request: {0}")]
    ExtractBytesFailed(#[from] axum::extract::rejection::BytesRejection),
    #[error("Body of {0} bytes exceeds the maximum of {1} bytes")]
    TooLarge(usize, usize),
}

impl From<DocsError> for ApiError {
    fn from(e: DocsError) -> Self {
        match e {
            DocsError::ExtractFailed => ApiError::from_err(&e, StatusCode::INTERNAL_SERVER_ERROR),
            DocsError::CrateDoesNotExist(_, _) => ApiError::from_err(&e, StatusCode::NOT_FOUND),
            DocsError::DatabaseError(db_error) => ApiError::from(db_error),
            DocsError::IoError(error) => ApiError::from(error),
            DocsError::CargoError(error) => {
                ApiError::new(&error, StatusCode::INTERNAL_SERVER_ERROR)
            }
            DocsError::StorageError(error) => ApiError::from(error),
            DocsError::ArchiveTooLarge => ApiError::from_err(&e, StatusCode::BAD_REQUEST),
            DocsError::BuildTimeout(_)
            | DocsError::BuildStopped
            | DocsError::PathPrefixMismatch { .. } => ApiError::internal(&e),
            // E.g. 413 if the body is larger than the configured maximum.
            DocsError::ExtractBytesFailed(ref rejection) => {
                let status = rejection.status();
                ApiError::from_err(&e, status)
            }
            DocsError::TooLarge(_, _) => ApiError::from_err(&e, StatusCode::PAYLOAD_TOO_LARGE),
        }
    }
}