Add default storage class to ListObjectsV2 (#765)

* Add InvalidRangeSpec error

* Add EntityTooSmall to from_u32

* Add InvalidRangeSpec to from_u32

* Map InvalidRangeSpec to correct S3ErrorCode

* Return Error::InvalidRangeSpec

* Use auto implementation

* Add default storage class to ListObjectsV2

Resolves #764

* Add storage_class to response

* Make storage class optional so default won't be an empty string

---------

Co-authored-by: houseme <housemecn@gmail.com>
This commit is contained in:
Niklas Mollenhauer
2025-10-31 12:32:25 +01:00
committed by GitHub
parent 325ff62684
commit 79012be2c8
2 changed files with 12 additions and 0 deletions

View File

@@ -14,6 +14,7 @@
use crate::bucket::metadata_sys::get_versioning_config;
use crate::bucket::versioning::VersioningApi as _;
use crate::config::storageclass;
use crate::disk::DiskStore;
use crate::error::{Error, Result};
use crate::store_utils::clean_metadata;
@@ -33,6 +34,7 @@ use rustfs_madmin::heal_commands::HealResultItem;
use rustfs_rio::Checksum;
use rustfs_rio::{DecompressReader, HashReader, LimitReader, WarpReader};
use rustfs_utils::CompressionAlgorithm;
use rustfs_utils::http::AMZ_STORAGE_CLASS;
use rustfs_utils::http::headers::{AMZ_OBJECT_TAGGING, RESERVED_METADATA_PREFIX_LOWER};
use rustfs_utils::path::decode_dir_object;
use serde::{Deserialize, Serialize};
@@ -518,6 +520,7 @@ impl From<s3s::dto::CompletedPart> for CompletePart {
pub struct ObjectInfo {
pub bucket: String,
pub name: String,
pub storage_class: Option<String>,
pub mod_time: Option<OffsetDateTime>,
pub size: i64,
// Actual size is the real size of the object uploaded by client.
@@ -557,6 +560,7 @@ impl Clone for ObjectInfo {
Self {
bucket: self.bucket.clone(),
name: self.name.clone(),
storage_class: self.storage_class.clone(),
mod_time: self.mod_time,
size: self.size,
actual_size: self.actual_size,
@@ -689,6 +693,12 @@ impl ObjectInfo {
v
};
// Extract storage class from metadata, default to STANDARD if not found
let storage_class = metadata
.get(AMZ_STORAGE_CLASS)
.cloned()
.or_else(|| Some(storageclass::STANDARD.to_string()));
// Convert parts from rustfs_filemeta::ObjectPartInfo to store_api::ObjectPartInfo
let parts = fi
.parts
@@ -727,6 +737,7 @@ impl ObjectInfo {
user_defined: metadata,
transitioned_object,
checksum: fi.checksum.clone(),
storage_class,
..Default::default()
}
}

View File

@@ -2218,6 +2218,7 @@ impl S3 for FS {
last_modified: v.mod_time.map(Timestamp::from),
size: Some(v.get_actual_size().unwrap_or_default()),
e_tag: v.etag.clone().map(|etag| to_s3s_etag(&etag)),
storage_class: v.storage_class.clone().map(ObjectStorageClass::from),
..Default::default()
};