71 lines
2.1 KiB
Rust
71 lines
2.1 KiB
Rust
|
|
use hyper::{Response, StatusCode};
|
||
|
|
use http_body_util::Full;
|
||
|
|
use bytes::Bytes;
|
||
|
|
|
||
|
|
#[derive(Debug, thiserror::Error)]
|
||
|
|
#[error("S3Error({code}): {message}")]
|
||
|
|
pub struct S3Error {
|
||
|
|
pub code: String,
|
||
|
|
pub message: String,
|
||
|
|
pub status: StatusCode,
|
||
|
|
}
|
||
|
|
|
||
|
|
impl S3Error {
|
||
|
|
pub fn new(code: &str, message: &str, status: StatusCode) -> Self {
|
||
|
|
Self {
|
||
|
|
code: code.to_string(),
|
||
|
|
message: message.to_string(),
|
||
|
|
status,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn no_such_key() -> Self {
|
||
|
|
Self::new("NoSuchKey", "The specified key does not exist.", StatusCode::NOT_FOUND)
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn no_such_bucket() -> Self {
|
||
|
|
Self::new("NoSuchBucket", "The specified bucket does not exist", StatusCode::NOT_FOUND)
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn bucket_not_empty() -> Self {
|
||
|
|
Self::new("BucketNotEmpty", "The bucket you tried to delete is not empty", StatusCode::CONFLICT)
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn access_denied() -> Self {
|
||
|
|
Self::new("AccessDenied", "Access Denied", StatusCode::FORBIDDEN)
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn no_such_upload() -> Self {
|
||
|
|
Self::new("NoSuchUpload", "The specified upload does not exist", StatusCode::NOT_FOUND)
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn invalid_part_number() -> Self {
|
||
|
|
Self::new("InvalidPartNumber", "Part number must be between 1 and 10000", StatusCode::BAD_REQUEST)
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn internal_error(msg: &str) -> Self {
|
||
|
|
Self::new("InternalError", msg, StatusCode::INTERNAL_SERVER_ERROR)
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn invalid_request(msg: &str) -> Self {
|
||
|
|
Self::new("InvalidRequest", msg, StatusCode::BAD_REQUEST)
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn to_xml(&self) -> String {
|
||
|
|
format!(
|
||
|
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Error><Code>{}</Code><Message>{}</Message></Error>",
|
||
|
|
self.code, self.message
|
||
|
|
)
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn to_response(&self, request_id: &str) -> Response<Full<Bytes>> {
|
||
|
|
let xml = self.to_xml();
|
||
|
|
Response::builder()
|
||
|
|
.status(self.status)
|
||
|
|
.header("content-type", "application/xml")
|
||
|
|
.header("x-amz-request-id", request_id)
|
||
|
|
.body(Full::new(Bytes::from(xml)))
|
||
|
|
.unwrap()
|
||
|
|
}
|
||
|
|
}
|