Skip to main content

kellnr_docs/
docs_error.rs

1use hyper::StatusCode;
2use kellnr_http::error::ApiError;
3use kellnr_storage::storage_error::StorageError;
4use thiserror::Error;
5
6#[derive(Error, Debug)]
7pub enum DocsError {
8    #[error("Failed to extract docs")]
9    ExtractFailed,
10    #[error("Crate with version does not exist: {0}-{1}")]
11    CrateDoesNotExist(String, String),
12    #[error("Database error: {0}")]
13    DatabaseError(#[from] kellnr_db::error::DbError),
14    #[error("IO error: {0}")]
15    IoError(#[from] std::io::Error),
16    #[error("Cargo error: {0}")]
17    CargoError(String),
18    #[error("Docs storage error: {0}")]
19    StorageError(#[from] StorageError),
20    #[error("Archive exceeds the maximum uncompressed size or number of entries")]
21    ArchiveTooLarge,
22    #[error("Docs build timed out after {0} seconds")]
23    BuildTimeout(u64),
24    #[error("Docs build stopped on shutdown")]
25    BuildStopped,
26    #[error("Path {path} is not inside {root}")]
27    PathPrefixMismatch { path: String, root: String },
28    #[error("Failed to extract bytes from request: {0}")]
29    ExtractBytesFailed(#[from] axum::extract::rejection::BytesRejection),
30    #[error("Body of {0} bytes exceeds the maximum of {1} bytes")]
31    TooLarge(usize, usize),
32}
33
34impl From<DocsError> for ApiError {
35    fn from(e: DocsError) -> Self {
36        match e {
37            DocsError::ExtractFailed => ApiError::from_err(&e, StatusCode::INTERNAL_SERVER_ERROR),
38            DocsError::CrateDoesNotExist(_, _) => ApiError::from_err(&e, StatusCode::NOT_FOUND),
39            DocsError::DatabaseError(db_error) => ApiError::from(db_error),
40            DocsError::IoError(error) => ApiError::from(error),
41            DocsError::CargoError(error) => {
42                ApiError::new(&error, StatusCode::INTERNAL_SERVER_ERROR)
43            }
44            DocsError::StorageError(error) => ApiError::from(error),
45            DocsError::ArchiveTooLarge => ApiError::from_err(&e, StatusCode::BAD_REQUEST),
46            DocsError::BuildTimeout(_)
47            | DocsError::BuildStopped
48            | DocsError::PathPrefixMismatch { .. } => ApiError::internal(&e),
49            // E.g. 413 if the body is larger than the configured maximum.
50            DocsError::ExtractBytesFailed(ref rejection) => {
51                let status = rejection.status();
52                ApiError::from_err(&e, status)
53            }
54            DocsError::TooLarge(_, _) => ApiError::from_err(&e, StatusCode::PAYLOAD_TOO_LARGE),
55        }
56    }
57}