mirror of
https://github.com/rustfs/rustfs.git
synced 2026-07-26 16:28:15 +00:00
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:
@@ -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
@@ -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."
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
// Reference:https://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"));
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user