Fix:s3 compatibility (#1617)

Co-authored-by: houseme <housemecn@gmail.com>
Co-authored-by: loverustfs <hello@rustfs.com>
Co-authored-by: heihutu <30542132+heihutu@users.noreply.github.com>
This commit is contained in:
LeonWang0735
2026-01-27 16:56:31 +08:00
committed by GitHub
parent 74759b6e99
commit 8edb1affc0
4 changed files with 19 additions and 14 deletions
+10 -3
View File
@@ -13,6 +13,7 @@
// limitations under the License.
use s3s::dto::Tag;
use std::cmp::Ordering;
use std::collections::HashMap;
use url::form_urlencoded;
@@ -22,7 +23,7 @@ pub fn decode_tags(tags: &str) -> Vec<Tag> {
let mut list = Vec::new();
for (k, v) in values {
if k.is_empty() || v.is_empty() {
if k.is_empty() {
continue;
}
@@ -31,7 +32,13 @@ pub fn decode_tags(tags: &str) -> Vec<Tag> {
value: Some(v.to_string()),
});
}
// use pattern matching instead of unwrap(), no panic even if the key becomes None later
list.sort_by(|a, b| match (a.key.as_ref(), b.key.as_ref()) {
(Some(a_k), Some(b_k)) => a_k.cmp(b_k),
(Some(_), None) => Ordering::Greater,
(None, Some(_)) => Ordering::Less,
(None, None) => Ordering::Equal,
});
list
}
@@ -39,7 +46,7 @@ pub fn decode_tags_to_map(tags: &str) -> HashMap<String, String> {
let mut list = HashMap::new();
for (k, v) in form_urlencoded::parse(tags.as_bytes()) {
if k.is_empty() || v.is_empty() {
if k.is_empty() {
continue;
}
+4 -1
View File
@@ -146,7 +146,10 @@ impl S3Auth for IAMAuth {
tracing::warn!("get_secret_key failed: iam not initialized, access_key: {access_key}");
}
Err(s3_error!(UnauthorizedAccess, "Your account is not signed up2, access_key: {access_key}"))
Err(s3_error!(
InvalidAccessKeyId,
"The Access Key Id you provided does not exist in our records."
))
}
}
+3 -6
View File
@@ -4385,7 +4385,7 @@ impl S3 for FS {
if let Err(err) = cfg.is_valid() {
warn!("put_bucket_policy err input {:?}, {:?}", &policy, err);
return Err(s3_error!(InvalidPolicyDocument));
return Err(s3_error!(MalformedPolicy));
}
let data = serde_json::to_vec(&cfg).map_err(|e| s3_error!(InternalError, "parse policy failed {:?}", e))?;
@@ -5206,16 +5206,13 @@ impl S3 for FS {
return Err(s3_error!(InvalidTag, "Tag key is too long, maximum allowed length is 128 characters"));
}
// allow to set the value of a tag to an empty string, but cannot set it to a null value.
// Referencehttps://docs.aws.amazon.com/zh_cn/AWSEC2/latest/UserGuide/Using_Tags.html#tag-restrictions
let value = tag.value.as_ref().ok_or_else(|| {
error!("Null tag value");
s3_error!(InvalidTag, "Tag value cannot be null")
})?;
if value.is_empty() {
error!("Empty tag value");
return Err(s3_error!(InvalidTag, "Tag value cannot be empty"));
}
if value.len() > 256 {
error!("Tag value too long: {} bytes", value.len());
return Err(s3_error!(InvalidTag, "Tag value is too long, maximum allowed length is 256 characters"));
+2 -4
View File
@@ -367,11 +367,11 @@ pub(crate) fn filter_object_metadata(metadata: &HashMap<String, String>) -> Opti
let mut filtered_metadata = HashMap::new();
for (k, v) in metadata {
let lower_key = k.to_ascii_lowercase();
// Skip internal/reserved metadata
if k.starts_with(RESERVED_METADATA_PREFIX_LOWER) {
if lower_key.starts_with(RESERVED_METADATA_PREFIX_LOWER) {
continue;
}
// Skip empty object lock values
if v.is_empty() && (k == &X_AMZ_OBJECT_LOCK_MODE.to_string() || k == &X_AMZ_OBJECT_LOCK_RETAIN_UNTIL_DATE.to_string()) {
continue;
@@ -382,8 +382,6 @@ pub(crate) fn filter_object_metadata(metadata: &HashMap<String, String>) -> Opti
continue;
}
let lower_key = k.to_ascii_lowercase();
// Skip standard HTTP headers (they are returned as separate headers, not metadata)
if EXCLUDED_HEADERS.contains(&lower_key.as_str()) {
continue;