aboutsummaryrefslogtreecommitdiff
path: root/src/api/s3
diff options
context:
space:
mode:
authorAlex Auvolat <alex@adnab.me>2022-05-13 15:04:53 +0200
committerAlex Auvolat <alex@adnab.me>2022-05-13 15:04:53 +0200
commit96b11524d53b3616a28f33e2b057655be1639f6f (patch)
tree324a8a9624c5b861fb5a09b0ae0e0c07f6b9614c /src/api/s3
parentc0fb9fd0fe553e5eda39dcb1a09f059bcd631b6c (diff)
downloadgarage-96b11524d53b3616a28f33e2b057655be1639f6f.tar.gz
garage-96b11524d53b3616a28f33e2b057655be1639f6f.zip
Error refactoring
Diffstat (limited to 'src/api/s3')
-rw-r--r--src/api/s3/api_server.rs2
-rw-r--r--src/api/s3/bucket.rs4
-rw-r--r--src/api/s3/copy.rs14
-rw-r--r--src/api/s3/get.rs8
-rw-r--r--src/api/s3/list.rs2
-rw-r--r--src/api/s3/post_object.rs34
-rw-r--r--src/api/s3/put.rs12
-rw-r--r--src/api/s3/router.rs2
-rw-r--r--src/api/s3/website.rs14
9 files changed, 46 insertions, 46 deletions
diff --git a/src/api/s3/api_server.rs b/src/api/s3/api_server.rs
index 2bf4a1bc..af9f03e7 100644
--- a/src/api/s3/api_server.rs
+++ b/src/api/s3/api_server.rs
@@ -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
)))
diff --git a/src/api/s3/bucket.rs b/src/api/s3/bucket.rs
index 93048a8c..6ecda2cd 100644
--- a/src/api/s3/bucket.rs
+++ b/src/api/s3/bucket.rs
@@ -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
)));
diff --git a/src/api/s3/copy.rs b/src/api/s3/copy.rs
index 4e94d887..825b8fc0 100644
--- a/src/api/s3/copy.rs
+++ b/src/api/s3/copy.rs
@@ -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",
))
}
};
diff --git a/src/api/s3/get.rs b/src/api/s3/get.rs
index 3edf22a6..794bd4e9 100644
--- a/src/api/s3/get.rs
+++ b/src/api/s3/get.rs
@@ -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) => {
diff --git a/src/api/s3/list.rs b/src/api/s3/list.rs
index e2848c57..d97aafe5 100644
--- a/src/api/s3/list.rs
+++ b/src/api/s3/list.rs
@@ -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:
diff --git a/src/api/s3/post_object.rs b/src/api/s3/post_object.rs
index 86fa7880..91648a19 100644
--- a/src/api/s3/post_object.rs
+++ b/src/api/s3/post_object.rs
@@ -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(&param_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(),
))));
}
diff --git a/src/api/s3/put.rs b/src/api/s3/put.rs
index 89aa8d84..d50e32b0 100644
--- a/src/api/s3/put.rs
+++ b/src/api/s3/put.rs
@@ -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."
));
}
diff --git a/src/api/s3/router.rs b/src/api/s3/router.rs
index 446ceb54..e920e162 100644
--- a/src/api/s3/router.rs
+++ b/src/api/s3/router.rs
@@ -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() {
diff --git a/src/api/s3/website.rs b/src/api/s3/website.rs
index 561130dc..4fc7b7bb 100644
--- a/src/api/s3/website.rs
+++ b/src/api/s3/website.rs
@@ -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?