mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-19 02:56:18 +00:00
fix(quota): close reservation bypasses
This commit is contained in:
@@ -748,9 +748,10 @@ async fn handle_authenticated_request(
|
||||
}
|
||||
|
||||
for (key, value) in info.user_defined.iter() {
|
||||
if key != "content-type" {
|
||||
let header_name = format!("x-object-meta-{}", key);
|
||||
response = response.header(header_name, value.as_str());
|
||||
if key != "content-type"
|
||||
&& let Some(key) = object::swift_response_user_metadata_key(key)
|
||||
{
|
||||
response = response.header(format!("x-object-meta-{key}"), value.as_str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -817,9 +818,10 @@ async fn handle_authenticated_request(
|
||||
|
||||
// Add custom metadata headers (X-Object-Meta-*)
|
||||
for (key, value) in info.user_defined.iter() {
|
||||
if key != "content-type" {
|
||||
let header_name = format!("x-object-meta-{}", key);
|
||||
response = response.header(header_name, value.as_str());
|
||||
if key != "content-type"
|
||||
&& let Some(key) = object::swift_response_user_metadata_key(key)
|
||||
{
|
||||
response = response.header(format!("x-object-meta-{key}"), value.as_str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -856,9 +858,10 @@ async fn handle_authenticated_request(
|
||||
|
||||
// Add custom metadata headers (X-Object-Meta-*)
|
||||
for (key, value) in info.user_defined.iter() {
|
||||
if key != "content-type" {
|
||||
let header_name = format!("x-object-meta-{}", key);
|
||||
response = response.header(header_name, value.as_str());
|
||||
if key != "content-type"
|
||||
&& let Some(key) = object::swift_response_user_metadata_key(key)
|
||||
{
|
||||
response = response.header(format!("x-object-meta-{key}"), value.as_str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1168,9 +1171,10 @@ async fn handle_object_get(
|
||||
}
|
||||
|
||||
for (key, value) in info.user_defined.iter() {
|
||||
if key != "content-type" {
|
||||
let header_name = format!("x-object-meta-{}", key);
|
||||
response = response.header(header_name, value.as_str());
|
||||
if key != "content-type"
|
||||
&& let Some(key) = object::swift_response_user_metadata_key(key)
|
||||
{
|
||||
response = response.header(format!("x-object-meta-{key}"), value.as_str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1237,9 +1241,10 @@ async fn handle_object_get(
|
||||
if key == "x-delete-at" {
|
||||
// Add X-Delete-At header directly (not as X-Object-Meta-*)
|
||||
response = response.header("x-delete-at", value.as_str());
|
||||
} else if key != "content-type" {
|
||||
let header_name = format!("x-object-meta-{}", key);
|
||||
response = response.header(header_name, value.as_str());
|
||||
} else if key != "content-type"
|
||||
&& let Some(key) = object::swift_response_user_metadata_key(key)
|
||||
{
|
||||
response = response.header(format!("x-object-meta-{key}"), value.as_str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1293,9 +1298,10 @@ async fn handle_object_head(
|
||||
if key == "x-delete-at" {
|
||||
// Add X-Delete-At header directly (not as X-Object-Meta-*)
|
||||
response = response.header("x-delete-at", value.as_str());
|
||||
} else if key != "content-type" {
|
||||
let header_name = format!("x-object-meta-{}", key);
|
||||
response = response.header(header_name, value.as_str());
|
||||
} else if key != "content-type"
|
||||
&& let Some(key) = object::swift_response_user_metadata_key(key)
|
||||
{
|
||||
response = response.header(format!("x-object-meta-{key}"), value.as_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -84,6 +84,24 @@ fn stored_swift_user_metadata_key(key: &str) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn swift_response_user_metadata_key(key: &str) -> Option<&str> {
|
||||
if rustfs_utils::http::is_internal_key(key)
|
||||
|| rustfs_utils::http::starts_with_ignore_ascii_case(key, "x-rustfs-encryption-")
|
||||
|| rustfs_utils::http::starts_with_ignore_ascii_case(key, "x-minio-encryption-")
|
||||
{
|
||||
return None;
|
||||
}
|
||||
if let Some(unescaped) = key.strip_prefix(USER_METADATA_PREFIX)
|
||||
&& (rustfs_utils::http::is_internal_key(unescaped)
|
||||
|| rustfs_utils::http::starts_with_ignore_ascii_case(unescaped, "x-amz-")
|
||||
|| rustfs_utils::http::starts_with_ignore_ascii_case(unescaped, "x-rustfs-encryption-")
|
||||
|| rustfs_utils::http::starts_with_ignore_ascii_case(unescaped, "x-minio-encryption-"))
|
||||
{
|
||||
return Some(unescaped);
|
||||
}
|
||||
Some(key)
|
||||
}
|
||||
|
||||
fn swift_user_metadata(headers: &HeaderMap) -> Option<HashMap<String, String>> {
|
||||
let mut metadata = HashMap::new();
|
||||
let mut present = false;
|
||||
@@ -1142,6 +1160,19 @@ mod tests {
|
||||
assert_eq!(stored_swift_user_metadata_key("description"), "description");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn swift_user_metadata_response_mapping_is_reversible_and_filters_internal_keys() {
|
||||
assert_eq!(
|
||||
swift_response_user_metadata_key("x-amz-meta-x-rustfs-internal-actual-size"),
|
||||
Some("x-rustfs-internal-actual-size")
|
||||
);
|
||||
assert_eq!(swift_response_user_metadata_key("x-amz-meta-x-amz-checksum"), Some("x-amz-checksum"));
|
||||
assert_eq!(swift_response_user_metadata_key("x-amz-meta-description"), Some("x-amz-meta-description"));
|
||||
assert_eq!(swift_response_user_metadata_key("description"), Some("description"));
|
||||
assert_eq!(swift_response_user_metadata_key("x-rustfs-internal-actual-size"), None);
|
||||
assert_eq!(swift_response_user_metadata_key("x-minio-internal-actual-size"), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_validate_object_name_empty() {
|
||||
let result = ObjectKeyMapper::validate_object_name("");
|
||||
|
||||
Reference in New Issue
Block a user