aboutsummaryrefslogtreecommitdiff
path: root/src/api/common_error.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/api/common_error.rs')
-rw-r--r--src/api/common_error.rs67
1 files changed, 65 insertions, 2 deletions
diff --git a/src/api/common_error.rs b/src/api/common_error.rs
index 48106e03..b6dbf059 100644
--- a/src/api/common_error.rs
+++ b/src/api/common_error.rs
@@ -6,7 +6,7 @@ use garage_util::error::Error as GarageError;
/// Errors of this crate
#[derive(Debug, Error)]
pub enum CommonError {
- // Category: internal error
+ // ---- INTERNAL ERRORS ----
/// Error related to deeper parts of Garage
#[error(display = "Internal error: {}", _0)]
InternalError(#[error(source)] GarageError),
@@ -19,9 +19,34 @@ pub enum CommonError {
#[error(display = "Internal error (HTTP error): {}", _0)]
Http(#[error(source)] http::Error),
- /// The client sent an invalid request
+ // ---- GENERIC CLIENT ERRORS ----
+ /// Proper authentication was not provided
+ #[error(display = "Forbidden: {}", _0)]
+ Forbidden(String),
+
+ /// Generic bad request response with custom message
#[error(display = "Bad request: {}", _0)]
BadRequest(String),
+
+ // ---- SPECIFIC ERROR CONDITIONS ----
+ // These have to be error codes referenced in the S3 spec here:
+ // https://docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html#ErrorCodeList
+ /// The bucket requested don't exists
+ #[error(display = "Bucket not found")]
+ NoSuchBucket,
+
+ /// Tried to create a bucket that already exist
+ #[error(display = "Bucket already exists")]
+ BucketAlreadyExists,
+
+ /// Tried to delete a non-empty bucket
+ #[error(display = "Tried to delete a non-empty bucket")]
+ BucketNotEmpty,
+
+ // Category: bad request
+ /// Bucket name is not valid according to AWS S3 specs
+ #[error(display = "Invalid bucket name")]
+ InvalidBucketName,
}
impl CommonError {
@@ -36,15 +61,53 @@ impl CommonError {
StatusCode::INTERNAL_SERVER_ERROR
}
CommonError::BadRequest(_) => StatusCode::BAD_REQUEST,
+ CommonError::Forbidden(_) => StatusCode::FORBIDDEN,
+ CommonError::NoSuchBucket => StatusCode::NOT_FOUND,
+ CommonError::BucketNotEmpty | CommonError::BucketAlreadyExists => StatusCode::CONFLICT,
+ CommonError::InvalidBucketName => StatusCode::BAD_REQUEST,
}
}
+ pub fn aws_code(&self) -> &'static str {
+ match self {
+ CommonError::Forbidden(_) => "AccessDenied",
+ CommonError::InternalError(
+ GarageError::Timeout
+ | GarageError::RemoteError(_)
+ | GarageError::Quorum(_, _, _, _),
+ ) => "ServiceUnavailable",
+ CommonError::InternalError(_) | CommonError::Hyper(_) | CommonError::Http(_) => {
+ "InternalError"
+ }
+ CommonError::BadRequest(_) => "InvalidRequest",
+ CommonError::NoSuchBucket => "NoSuchBucket",
+ CommonError::BucketAlreadyExists => "BucketAlreadyExists",
+ CommonError::BucketNotEmpty => "BucketNotEmpty",
+ CommonError::InvalidBucketName => "InvalidBucketName",
+ }
+ }
pub fn bad_request<M: ToString>(msg: M) -> Self {
CommonError::BadRequest(msg.to_string())
}
}
+pub trait CommonErrorDerivative: From<CommonError> {
+ fn internal_error<M: ToString>(msg: M) -> Self {
+ Self::from(CommonError::InternalError(GarageError::Message(
+ msg.to_string(),
+ )))
+ }
+
+ fn bad_request<M: ToString>(msg: M) -> Self {
+ Self::from(CommonError::BadRequest(msg.to_string()))
+ }
+
+ fn forbidden<M: ToString>(msg: M) -> Self {
+ Self::from(CommonError::Forbidden(msg.to_string()))
+ }
+}
+
/// Trait to map error to the Bad Request error code
pub trait OkOrBadRequest {
type S;