mirror of
https://github.com/rustfs/rustfs.git
synced 2026-07-27 00:38:16 +00:00
fix(s3): return NoSuchUpload for abort_multipart_upload when upload_id not found (#1569)
Signed-off-by: 安正超 <anzhengchao@gmail.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
+7
-1
@@ -219,6 +219,7 @@ impl From<StorageError> for ApiError {
|
||||
StorageError::SlowDown => S3ErrorCode::SlowDown,
|
||||
StorageError::PrefixAccessDenied(_, _) => S3ErrorCode::AccessDenied,
|
||||
StorageError::InvalidUploadIDKeyCombination(_, _) => S3ErrorCode::InvalidArgument,
|
||||
StorageError::MalformedUploadID(_) => S3ErrorCode::InvalidArgument,
|
||||
StorageError::ObjectNameTooLong(_, _) => S3ErrorCode::InvalidArgument,
|
||||
StorageError::ObjectNamePrefixAsSlash(_, _) => S3ErrorCode::InvalidArgument,
|
||||
StorageError::ObjectNotFound(_, _) => S3ErrorCode::NoSuchKey,
|
||||
@@ -227,7 +228,7 @@ impl From<StorageError> for ApiError {
|
||||
StorageError::FileNotFound => S3ErrorCode::NoSuchKey,
|
||||
StorageError::FileVersionNotFound => S3ErrorCode::NoSuchVersion,
|
||||
StorageError::VersionNotFound(_, _, _) => S3ErrorCode::NoSuchVersion,
|
||||
StorageError::InvalidUploadID(_, _, _) => S3ErrorCode::InvalidPart,
|
||||
StorageError::InvalidUploadID(_, _, _) => S3ErrorCode::NoSuchUpload,
|
||||
StorageError::InvalidVersionID(_, _, _) => S3ErrorCode::InvalidArgument,
|
||||
StorageError::DataMovementOverwriteErr(_, _, _) => S3ErrorCode::InvalidArgument,
|
||||
StorageError::ObjectExistsAsDirectory(_, _) => S3ErrorCode::InvalidArgument,
|
||||
@@ -415,6 +416,11 @@ mod tests {
|
||||
(StorageError::VolumeNotFound, S3ErrorCode::NoSuchBucket),
|
||||
(StorageError::FileNotFound, S3ErrorCode::NoSuchKey),
|
||||
(StorageError::FileVersionNotFound, S3ErrorCode::NoSuchVersion),
|
||||
(StorageError::MalformedUploadID("test".into()), S3ErrorCode::InvalidArgument),
|
||||
(
|
||||
StorageError::InvalidUploadID("bucket".into(), "object".into(), "uploadid".into()),
|
||||
S3ErrorCode::NoSuchUpload,
|
||||
),
|
||||
];
|
||||
|
||||
for (storage_error, expected_code) in test_cases {
|
||||
|
||||
@@ -4902,11 +4902,25 @@ impl S3 for FS {
|
||||
|
||||
let opts = &ObjectOptions::default();
|
||||
|
||||
store
|
||||
// Special handling for abort_multipart_upload: Per AWS S3 API specification, this operation
|
||||
// should return NoSuchUpload (404) when the upload_id doesn't exist, even if the format
|
||||
// appears invalid. This differs from other multipart operations (upload_part, list_parts,
|
||||
// complete_multipart_upload) which return InvalidArgument for malformed upload_ids.
|
||||
// The lenient validation matches AWS S3 behavior where format validation is relaxed for
|
||||
// abort operations to avoid leaking information about upload_id format requirements.
|
||||
match store
|
||||
.abort_multipart_upload(bucket.as_str(), key.as_str(), upload_id.as_str(), opts)
|
||||
.await
|
||||
.map_err(ApiError::from)?;
|
||||
Ok(S3Response::new(AbortMultipartUploadOutput { ..Default::default() }))
|
||||
{
|
||||
Ok(_) => Ok(S3Response::new(AbortMultipartUploadOutput { ..Default::default() })),
|
||||
Err(err) => {
|
||||
// Convert MalformedUploadID to NoSuchUpload for S3 API compatibility
|
||||
if matches!(err, StorageError::MalformedUploadID(_)) {
|
||||
return Err(S3Error::new(S3ErrorCode::NoSuchUpload));
|
||||
}
|
||||
Err(ApiError::from(err).into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
|
||||
@@ -138,3 +138,4 @@ test_ranged_request_empty_object
|
||||
test_ranged_request_invalid_range
|
||||
test_set_multipart_tagging
|
||||
test_upload_part_copy_percent_encoded_key
|
||||
test_api_error_from_storage_error_mappings
|
||||
|
||||
Reference in New Issue
Block a user