mirror of
https://github.com/deuxfleurs-org/garage.git
synced 2026-08-13 15:46:53 +00:00
Error refactoring
This commit is contained in:
@@ -310,7 +310,7 @@ impl ApiHandler for S3ApiServer {
|
||||
)
|
||||
.await
|
||||
} else {
|
||||
Err(Error::BadRequest(format!(
|
||||
Err(Error::bad_request(format!(
|
||||
"Invalid endpoint: list-type={}",
|
||||
list_type
|
||||
)))
|
||||
|
||||
@@ -130,7 +130,7 @@ pub async fn handle_create_bucket(
|
||||
|
||||
if let Some(location_constraint) = cmd {
|
||||
if location_constraint != garage.config.s3_api.s3_region {
|
||||
return Err(Error::BadRequest(format!(
|
||||
return Err(Error::bad_request(format!(
|
||||
"Cannot satisfy location constraint `{}`: buckets can only be created in region `{}`",
|
||||
location_constraint,
|
||||
garage.config.s3_api.s3_region
|
||||
@@ -163,7 +163,7 @@ pub async fn handle_create_bucket(
|
||||
} else {
|
||||
// Create the bucket!
|
||||
if !is_valid_bucket_name(&bucket_name) {
|
||||
return Err(Error::BadRequest(format!(
|
||||
return Err(Error::bad_request(format!(
|
||||
"{}: {}",
|
||||
bucket_name, INVALID_BUCKET_NAME_MESSAGE
|
||||
)));
|
||||
|
||||
+7
-7
@@ -201,8 +201,8 @@ pub async fn handle_upload_part_copy(
|
||||
let mut ranges = http_range::HttpRange::parse(range_str, source_version_meta.size)
|
||||
.map_err(|e| (e, source_version_meta.size))?;
|
||||
if ranges.len() != 1 {
|
||||
return Err(Error::BadRequest(
|
||||
"Invalid x-amz-copy-source-range header: exactly 1 range must be given".into(),
|
||||
return Err(Error::bad_request(
|
||||
"Invalid x-amz-copy-source-range header: exactly 1 range must be given",
|
||||
));
|
||||
} else {
|
||||
ranges.pop().unwrap()
|
||||
@@ -230,8 +230,8 @@ pub async fn handle_upload_part_copy(
|
||||
// This is only for small files, we don't bother handling this.
|
||||
// (in AWS UploadPartCopy works for parts at least 5MB which
|
||||
// is never the case of an inline object)
|
||||
return Err(Error::BadRequest(
|
||||
"Source object is too small (minimum part size is 5Mb)".into(),
|
||||
return Err(Error::bad_request(
|
||||
"Source object is too small (minimum part size is 5Mb)",
|
||||
));
|
||||
}
|
||||
ObjectVersionData::FirstBlock(_meta, _first_block_hash) => (),
|
||||
@@ -250,7 +250,7 @@ pub async fn handle_upload_part_copy(
|
||||
// Check this part number hasn't yet been uploaded
|
||||
if let Some(dv) = dest_version {
|
||||
if dv.has_part_number(part_number) {
|
||||
return Err(Error::BadRequest(format!(
|
||||
return Err(Error::bad_request(format!(
|
||||
"Part number {} has already been uploaded",
|
||||
part_number
|
||||
)));
|
||||
@@ -536,8 +536,8 @@ impl CopyPreconditionHeaders {
|
||||
(None, None, None, Some(ims)) => v_date > *ims,
|
||||
(None, None, None, None) => true,
|
||||
_ => {
|
||||
return Err(Error::BadRequest(
|
||||
"Invalid combination of x-amz-copy-source-if-xxxxx headers".into(),
|
||||
return Err(Error::bad_request(
|
||||
"Invalid combination of x-amz-copy-source-if-xxxxx headers",
|
||||
))
|
||||
}
|
||||
};
|
||||
|
||||
+4
-4
@@ -210,8 +210,8 @@ pub async fn handle_get(
|
||||
|
||||
match (part_number, parse_range_header(req, last_v_meta.size)?) {
|
||||
(Some(_), Some(_)) => {
|
||||
return Err(Error::BadRequest(
|
||||
"Cannot specify both partNumber and Range header".into(),
|
||||
return Err(Error::bad_request(
|
||||
"Cannot specify both partNumber and Range header",
|
||||
));
|
||||
}
|
||||
(Some(pn), None) => {
|
||||
@@ -302,9 +302,9 @@ async fn handle_get_range(
|
||||
let body: Body = Body::from(bytes[begin as usize..end as usize].to_vec());
|
||||
Ok(resp_builder.body(body)?)
|
||||
} else {
|
||||
None.ok_or_internal_error(
|
||||
Err(Error::internal_error(
|
||||
"Requested range not present in inline bytes when it should have been",
|
||||
)
|
||||
))
|
||||
}
|
||||
}
|
||||
ObjectVersionData::FirstBlock(_meta, _first_block_hash) => {
|
||||
|
||||
+1
-1
@@ -588,7 +588,7 @@ impl ListObjectsQuery {
|
||||
"]" => Ok(RangeBegin::AfterKey {
|
||||
key: String::from_utf8(base64::decode(token[1..].as_bytes())?)?,
|
||||
}),
|
||||
_ => Err(Error::BadRequest("Invalid continuation token".to_string())),
|
||||
_ => Err(Error::bad_request("Invalid continuation token".to_string())),
|
||||
},
|
||||
|
||||
// StartAfter has defined semantics in the spec:
|
||||
|
||||
+17
-17
@@ -48,7 +48,7 @@ pub async fn handle_post_object(
|
||||
let field = if let Some(field) = multipart.next_field().await? {
|
||||
field
|
||||
} else {
|
||||
return Err(Error::BadRequest(
|
||||
return Err(Error::bad_request(
|
||||
"Request did not contain a file".to_owned(),
|
||||
));
|
||||
};
|
||||
@@ -66,14 +66,14 @@ pub async fn handle_post_object(
|
||||
"tag" => (/* tag need to be reencoded, but we don't support them yet anyway */),
|
||||
"acl" => {
|
||||
if params.insert("x-amz-acl", content).is_some() {
|
||||
return Err(Error::BadRequest(
|
||||
return Err(Error::bad_request(
|
||||
"Field 'acl' provided more than one time".to_string(),
|
||||
));
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
if params.insert(&name, content).is_some() {
|
||||
return Err(Error::BadRequest(format!(
|
||||
return Err(Error::bad_request(format!(
|
||||
"Field '{}' provided more than one time",
|
||||
name
|
||||
)));
|
||||
@@ -145,7 +145,7 @@ pub async fn handle_post_object(
|
||||
.ok_or_bad_request("Invalid expiration date")?
|
||||
.into();
|
||||
if Utc::now() - expiration > Duration::zero() {
|
||||
return Err(Error::BadRequest(
|
||||
return Err(Error::bad_request(
|
||||
"Expiration date is in the paste".to_string(),
|
||||
));
|
||||
}
|
||||
@@ -159,7 +159,7 @@ pub async fn handle_post_object(
|
||||
"policy" | "x-amz-signature" => (), // this is always accepted, as it's required to validate other fields
|
||||
"content-type" => {
|
||||
let conds = conditions.params.remove("content-type").ok_or_else(|| {
|
||||
Error::BadRequest(format!("Key '{}' is not allowed in policy", param_key))
|
||||
Error::bad_request(format!("Key '{}' is not allowed in policy", param_key))
|
||||
})?;
|
||||
for cond in conds {
|
||||
let ok = match cond {
|
||||
@@ -169,7 +169,7 @@ pub async fn handle_post_object(
|
||||
}
|
||||
};
|
||||
if !ok {
|
||||
return Err(Error::BadRequest(format!(
|
||||
return Err(Error::bad_request(format!(
|
||||
"Key '{}' has value not allowed in policy",
|
||||
param_key
|
||||
)));
|
||||
@@ -178,7 +178,7 @@ pub async fn handle_post_object(
|
||||
}
|
||||
"key" => {
|
||||
let conds = conditions.params.remove("key").ok_or_else(|| {
|
||||
Error::BadRequest(format!("Key '{}' is not allowed in policy", param_key))
|
||||
Error::bad_request(format!("Key '{}' is not allowed in policy", param_key))
|
||||
})?;
|
||||
for cond in conds {
|
||||
let ok = match cond {
|
||||
@@ -186,7 +186,7 @@ pub async fn handle_post_object(
|
||||
Operation::StartsWith(s) => key.starts_with(&s),
|
||||
};
|
||||
if !ok {
|
||||
return Err(Error::BadRequest(format!(
|
||||
return Err(Error::bad_request(format!(
|
||||
"Key '{}' has value not allowed in policy",
|
||||
param_key
|
||||
)));
|
||||
@@ -201,7 +201,7 @@ pub async fn handle_post_object(
|
||||
continue;
|
||||
}
|
||||
let conds = conditions.params.remove(¶m_key).ok_or_else(|| {
|
||||
Error::BadRequest(format!("Key '{}' is not allowed in policy", param_key))
|
||||
Error::bad_request(format!("Key '{}' is not allowed in policy", param_key))
|
||||
})?;
|
||||
for cond in conds {
|
||||
let ok = match cond {
|
||||
@@ -209,7 +209,7 @@ pub async fn handle_post_object(
|
||||
Operation::StartsWith(s) => value.to_str()?.starts_with(s.as_str()),
|
||||
};
|
||||
if !ok {
|
||||
return Err(Error::BadRequest(format!(
|
||||
return Err(Error::bad_request(format!(
|
||||
"Key '{}' has value not allowed in policy",
|
||||
param_key
|
||||
)));
|
||||
@@ -220,7 +220,7 @@ pub async fn handle_post_object(
|
||||
}
|
||||
|
||||
if let Some((param_key, _)) = conditions.params.iter().next() {
|
||||
return Err(Error::BadRequest(format!(
|
||||
return Err(Error::bad_request(format!(
|
||||
"Key '{}' is required in policy, but no value was provided",
|
||||
param_key
|
||||
)));
|
||||
@@ -326,7 +326,7 @@ impl Policy {
|
||||
match condition {
|
||||
PolicyCondition::Equal(map) => {
|
||||
if map.len() != 1 {
|
||||
return Err(Error::BadRequest("Invalid policy item".to_owned()));
|
||||
return Err(Error::bad_request("Invalid policy item".to_owned()));
|
||||
}
|
||||
let (mut k, v) = map.into_iter().next().expect("size was verified");
|
||||
k.make_ascii_lowercase();
|
||||
@@ -334,7 +334,7 @@ impl Policy {
|
||||
}
|
||||
PolicyCondition::OtherOp([cond, mut key, value]) => {
|
||||
if key.remove(0) != '$' {
|
||||
return Err(Error::BadRequest("Invalid policy item".to_owned()));
|
||||
return Err(Error::bad_request("Invalid policy item".to_owned()));
|
||||
}
|
||||
key.make_ascii_lowercase();
|
||||
match cond.as_str() {
|
||||
@@ -347,7 +347,7 @@ impl Policy {
|
||||
.or_default()
|
||||
.push(Operation::StartsWith(value));
|
||||
}
|
||||
_ => return Err(Error::BadRequest("Invalid policy item".to_owned())),
|
||||
_ => return Err(Error::bad_request("Invalid policy item".to_owned())),
|
||||
}
|
||||
}
|
||||
PolicyCondition::SizeRange(key, min, max) => {
|
||||
@@ -355,7 +355,7 @@ impl Policy {
|
||||
length.0 = length.0.max(min);
|
||||
length.1 = length.1.min(max);
|
||||
} else {
|
||||
return Err(Error::BadRequest("Invalid policy item".to_owned()));
|
||||
return Err(Error::bad_request("Invalid policy item".to_owned()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -420,14 +420,14 @@ where
|
||||
self.read += bytes.len() as u64;
|
||||
// optimization to fail early when we know before the end it's too long
|
||||
if self.length.end() < &self.read {
|
||||
return Poll::Ready(Some(Err(Error::BadRequest(
|
||||
return Poll::Ready(Some(Err(Error::bad_request(
|
||||
"File size does not match policy".to_owned(),
|
||||
))));
|
||||
}
|
||||
}
|
||||
Poll::Ready(None) => {
|
||||
if !self.length.contains(&self.read) {
|
||||
return Poll::Ready(Some(Err(Error::BadRequest(
|
||||
return Poll::Ready(Some(Err(Error::bad_request(
|
||||
"File size does not match policy".to_owned(),
|
||||
))));
|
||||
}
|
||||
|
||||
+6
-6
@@ -183,7 +183,7 @@ fn ensure_checksum_matches(
|
||||
) -> Result<(), Error> {
|
||||
if let Some(expected_sha256) = content_sha256 {
|
||||
if expected_sha256 != data_sha256sum {
|
||||
return Err(Error::BadRequest(
|
||||
return Err(Error::bad_request(
|
||||
"Unable to validate x-amz-content-sha256".to_string(),
|
||||
));
|
||||
} else {
|
||||
@@ -192,7 +192,7 @@ fn ensure_checksum_matches(
|
||||
}
|
||||
if let Some(expected_md5) = content_md5 {
|
||||
if expected_md5.trim_matches('"') != base64::encode(data_md5sum) {
|
||||
return Err(Error::BadRequest(
|
||||
return Err(Error::bad_request(
|
||||
"Unable to validate content-md5".to_string(),
|
||||
));
|
||||
} else {
|
||||
@@ -428,7 +428,7 @@ pub async fn handle_put_part(
|
||||
// Check part hasn't already been uploaded
|
||||
if let Some(v) = version {
|
||||
if v.has_part_number(part_number) {
|
||||
return Err(Error::BadRequest(format!(
|
||||
return Err(Error::bad_request(format!(
|
||||
"Part number {} has already been uploaded",
|
||||
part_number
|
||||
)));
|
||||
@@ -513,7 +513,7 @@ pub async fn handle_complete_multipart_upload(
|
||||
|
||||
let version = version.ok_or(Error::NoSuchKey)?;
|
||||
if version.blocks.is_empty() {
|
||||
return Err(Error::BadRequest("No data was uploaded".to_string()));
|
||||
return Err(Error::bad_request("No data was uploaded".to_string()));
|
||||
}
|
||||
|
||||
let headers = match object_version.state {
|
||||
@@ -574,8 +574,8 @@ pub async fn handle_complete_multipart_upload(
|
||||
.map(|x| x.part_number)
|
||||
.eq(block_parts.into_iter());
|
||||
if !same_parts {
|
||||
return Err(Error::BadRequest(
|
||||
"Part numbers in block list and part list do not match. This can happen if a part was partially uploaded. Please abort the multipart upload and try again.".into(),
|
||||
return Err(Error::bad_request(
|
||||
"Part numbers in block list and part list do not match. This can happen if a part was partially uploaded. Please abort the multipart upload and try again."
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
@@ -342,7 +342,7 @@ impl Endpoint {
|
||||
Method::POST => Self::from_post(key, &mut query)?,
|
||||
Method::PUT => Self::from_put(key, &mut query, req.headers())?,
|
||||
Method::DELETE => Self::from_delete(key, &mut query)?,
|
||||
_ => return Err(Error::BadRequest("Unknown method".to_owned())),
|
||||
_ => return Err(Error::bad_request("Unknown method".to_owned())),
|
||||
};
|
||||
|
||||
if let Some(message) = query.nonempty_message() {
|
||||
|
||||
@@ -176,7 +176,7 @@ impl WebsiteConfiguration {
|
||||
|| self.index_document.is_some()
|
||||
|| self.routing_rules.is_some())
|
||||
{
|
||||
return Err(Error::BadRequest(
|
||||
return Err(Error::bad_request(
|
||||
"Bad XML: can't have RedirectAllRequestsTo and other fields".to_owned(),
|
||||
));
|
||||
}
|
||||
@@ -222,7 +222,7 @@ impl WebsiteConfiguration {
|
||||
impl Key {
|
||||
pub fn validate(&self) -> Result<(), Error> {
|
||||
if self.key.0.is_empty() {
|
||||
Err(Error::BadRequest(
|
||||
Err(Error::bad_request(
|
||||
"Bad XML: error document specified but empty".to_owned(),
|
||||
))
|
||||
} else {
|
||||
@@ -234,7 +234,7 @@ impl Key {
|
||||
impl Suffix {
|
||||
pub fn validate(&self) -> Result<(), Error> {
|
||||
if self.suffix.0.is_empty() | self.suffix.0.contains('/') {
|
||||
Err(Error::BadRequest(
|
||||
Err(Error::bad_request(
|
||||
"Bad XML: index document is empty or contains /".to_owned(),
|
||||
))
|
||||
} else {
|
||||
@@ -247,7 +247,7 @@ impl Target {
|
||||
pub fn validate(&self) -> Result<(), Error> {
|
||||
if let Some(ref protocol) = self.protocol {
|
||||
if protocol.0 != "http" && protocol.0 != "https" {
|
||||
return Err(Error::BadRequest("Bad XML: invalid protocol".to_owned()));
|
||||
return Err(Error::bad_request("Bad XML: invalid protocol".to_owned()));
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
@@ -269,19 +269,19 @@ impl Redirect {
|
||||
pub fn validate(&self, has_prefix: bool) -> Result<(), Error> {
|
||||
if self.replace_prefix.is_some() {
|
||||
if self.replace_full.is_some() {
|
||||
return Err(Error::BadRequest(
|
||||
return Err(Error::bad_request(
|
||||
"Bad XML: both ReplaceKeyPrefixWith and ReplaceKeyWith are set".to_owned(),
|
||||
));
|
||||
}
|
||||
if !has_prefix {
|
||||
return Err(Error::BadRequest(
|
||||
return Err(Error::bad_request(
|
||||
"Bad XML: ReplaceKeyPrefixWith is set, but KeyPrefixEquals isn't".to_owned(),
|
||||
));
|
||||
}
|
||||
}
|
||||
if let Some(ref protocol) = self.protocol {
|
||||
if protocol.0 != "http" && protocol.0 != "https" {
|
||||
return Err(Error::BadRequest("Bad XML: invalid protocol".to_owned()));
|
||||
return Err(Error::bad_request("Bad XML: invalid protocol".to_owned()));
|
||||
}
|
||||
}
|
||||
// TODO there are probably more invalide cases, but which ones?
|
||||
|
||||
Reference in New Issue
Block a user