refactor(storage): extract remaining s3_api response builders (#1937)

This commit is contained in:
安正超
2026-02-24 21:57:43 +08:00
committed by GitHub
parent 1b1fd6295d
commit f4874ec89d
9 changed files with 204 additions and 29 deletions
+11 -10
View File
@@ -25,6 +25,7 @@ use crate::storage::ecfs::{
stored_acl_from_grant_headers, stored_acl_from_policy, stored_grant_to_dto, stored_owner_to_dto,
};
use crate::storage::helper::OperationHelper;
use crate::storage::s3_api::{encryption, replication, tagging};
use crate::storage::*;
use futures::StreamExt;
use http::StatusCode;
@@ -651,7 +652,7 @@ impl DefaultBucketUsecase {
.await
.map_err(ApiError::from)?;
Ok(S3Response::new(DeleteBucketTaggingOutput {}))
Ok(S3Response::new(tagging::build_delete_bucket_tagging_output()))
}
#[instrument(level = "debug", skip(self))]
@@ -708,9 +709,9 @@ impl DefaultBucketUsecase {
}
};
Ok(S3Response::new(GetBucketEncryptionOutput {
Ok(S3Response::new(encryption::build_get_bucket_encryption_output(
server_side_encryption_configuration,
}))
)))
}
#[instrument(level = "debug", skip(self))]
@@ -986,9 +987,9 @@ impl DefaultBucketUsecase {
}
};
Ok(S3Response::new(GetBucketReplicationOutput {
replication_configuration: Some(replication_configuration),
}))
Ok(S3Response::new(replication::build_get_bucket_replication_output(
replication_configuration,
)))
}
#[instrument(level = "debug", skip(self))]
@@ -1022,7 +1023,7 @@ impl DefaultBucketUsecase {
}
};
Ok(S3Response::new(GetBucketTaggingOutput { tag_set }))
Ok(S3Response::new(tagging::build_get_bucket_tagging_output(tag_set)))
}
#[instrument(level = "debug", skip(self))]
@@ -1119,7 +1120,7 @@ impl DefaultBucketUsecase {
metadata_sys::update(&bucket, BUCKET_SSECONFIG, data)
.await
.map_err(ApiError::from)?;
Ok(S3Response::new(PutBucketEncryptionOutput::default()))
Ok(S3Response::new(encryption::build_put_bucket_encryption_output()))
}
#[instrument(level = "debug", skip(self))]
@@ -1345,7 +1346,7 @@ impl DefaultBucketUsecase {
.await
.map_err(ApiError::from)?;
Ok(S3Response::new(PutBucketReplicationOutput::default()))
Ok(S3Response::new(replication::build_put_bucket_replication_output()))
}
#[instrument(level = "debug", skip(self))]
@@ -1406,7 +1407,7 @@ impl DefaultBucketUsecase {
.await
.map_err(ApiError::from)?;
Ok(S3Response::new(Default::default()))
Ok(S3Response::new(tagging::build_put_bucket_tagging_output()))
}
#[instrument(level = "debug", skip(self))]
+7 -11
View File
@@ -29,6 +29,7 @@ use crate::storage::options::{
copy_dst_opts, copy_src_opts, del_opts, extract_metadata, extract_metadata_from_mime_with_object_name,
filter_object_metadata, get_content_sha256, get_opts, put_opts,
};
use crate::storage::s3_api::{restore, select};
use crate::storage::*;
use base64::{Engine, engine::general_purpose::STANDARD as BASE64_STANDARD};
use bytes::Bytes;
@@ -3335,10 +3336,8 @@ impl DefaultObjectUsecase {
.map_err(|_| S3Error::with_message(S3ErrorCode::Custom("ErrCopyObject".into()), "restore object failed."))?;
if already_restored {
let output = RestoreObjectOutput {
request_charged: Some(RequestCharged::from_static(RequestCharged::REQUESTER)),
restore_output_path: None,
};
let output =
restore::build_restore_object_output(Some(RequestCharged::from_static(RequestCharged::REQUESTER)), None);
return Ok(S3Response::new(output));
}
}
@@ -3389,10 +3388,7 @@ impl DefaultObjectUsecase {
}
});
let output = RestoreObjectOutput {
request_charged: Some(RequestCharged::from_static(RequestCharged::REQUESTER)),
restore_output_path: None,
};
let output = restore::build_restore_object_output(Some(RequestCharged::from_static(RequestCharged::REQUESTER)), None);
Ok(S3Response::with_headers(output, header))
}
@@ -3471,9 +3467,9 @@ impl DefaultObjectUsecase {
drop(tx);
});
Ok(S3Response::new(SelectObjectContentOutput {
payload: Some(SelectObjectContentEventStream::new(stream)),
}))
Ok(S3Response::new(select::build_select_object_content_output(
SelectObjectContentEventStream::new(stream),
)))
}
}
+1
View File
@@ -18,6 +18,7 @@ pub mod ecfs;
pub(crate) mod entity;
pub(crate) mod helper;
pub mod options;
pub(crate) mod s3_api;
pub mod tonic_service;
#[cfg(test)]
+47
View File
@@ -0,0 +1,47 @@
// Copyright 2024 RustFS Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use s3s::dto::{GetBucketEncryptionOutput, PutBucketEncryptionOutput, ServerSideEncryptionConfiguration};
pub(crate) fn build_get_bucket_encryption_output(
server_side_encryption_configuration: Option<ServerSideEncryptionConfiguration>,
) -> GetBucketEncryptionOutput {
GetBucketEncryptionOutput {
server_side_encryption_configuration,
}
}
pub(crate) fn build_put_bucket_encryption_output() -> PutBucketEncryptionOutput {
PutBucketEncryptionOutput::default()
}
#[cfg(test)]
mod tests {
use super::{build_get_bucket_encryption_output, build_put_bucket_encryption_output};
use s3s::dto::ServerSideEncryptionConfiguration;
#[test]
fn test_build_get_bucket_encryption_output_preserves_configuration() {
let config = Some(ServerSideEncryptionConfiguration::default());
let output = build_get_bucket_encryption_output(config.clone());
assert_eq!(output.server_side_encryption_configuration, config);
}
#[test]
fn test_build_put_bucket_encryption_output_is_default() {
let output = build_put_bucket_encryption_output();
assert_eq!(output, Default::default());
}
}
+5 -4
View File
@@ -16,11 +16,12 @@
//!
//! This file intentionally starts as skeleton-only. Behavior remains in place
//! until each helper is moved with dedicated small refactor steps.
#![allow(dead_code)]
pub(crate) mod acl;
pub(crate) mod bucket;
pub(crate) mod common;
pub(crate) mod encryption {}
pub(crate) mod encryption;
pub(crate) mod multipart;
pub(crate) mod object_lock;
/// Object helper facade placeholder.
@@ -29,9 +30,9 @@ pub(crate) mod object_lock;
/// modules (for example, `storage::readers`) and be consumed from there.
/// Object-specific extraction steps can be added here incrementally.
pub(crate) mod object {}
pub(crate) mod replication {}
pub(crate) mod replication;
pub(crate) mod response;
pub(crate) mod restore {}
pub(crate) mod select {}
pub(crate) mod restore;
pub(crate) mod select;
pub(crate) mod tagging;
pub(crate) mod validation {}
+47
View File
@@ -0,0 +1,47 @@
// Copyright 2024 RustFS Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use s3s::dto::{GetBucketReplicationOutput, PutBucketReplicationOutput, ReplicationConfiguration};
pub(crate) fn build_get_bucket_replication_output(
replication_configuration: ReplicationConfiguration,
) -> GetBucketReplicationOutput {
GetBucketReplicationOutput {
replication_configuration: Some(replication_configuration),
}
}
pub(crate) fn build_put_bucket_replication_output() -> PutBucketReplicationOutput {
PutBucketReplicationOutput::default()
}
#[cfg(test)]
mod tests {
use super::{build_get_bucket_replication_output, build_put_bucket_replication_output};
use s3s::dto::ReplicationConfiguration;
#[test]
fn test_build_get_bucket_replication_output_sets_configuration() {
let config = ReplicationConfiguration::default();
let output = build_get_bucket_replication_output(config.clone());
assert_eq!(output.replication_configuration, Some(config));
}
#[test]
fn test_build_put_bucket_replication_output_is_default() {
let output = build_put_bucket_replication_output();
assert_eq!(output, Default::default());
}
}
+42
View File
@@ -0,0 +1,42 @@
// Copyright 2024 RustFS Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use s3s::dto::{RequestCharged, RestoreObjectOutput};
pub(crate) fn build_restore_object_output(
request_charged: Option<RequestCharged>,
restore_output_path: Option<String>,
) -> RestoreObjectOutput {
RestoreObjectOutput {
request_charged,
restore_output_path,
}
}
#[cfg(test)]
mod tests {
use super::build_restore_object_output;
use s3s::dto::RequestCharged;
#[test]
fn test_build_restore_object_output_preserves_fields() {
let output = build_restore_object_output(
Some(RequestCharged::from_static(RequestCharged::REQUESTER)),
Some("s3://bucket/prefix/id".to_string()),
);
assert_eq!(output.request_charged, Some(RequestCharged::from_static(RequestCharged::REQUESTER)));
assert_eq!(output.restore_output_path, Some("s3://bucket/prefix/id".to_string()));
}
}
+19
View File
@@ -0,0 +1,19 @@
// Copyright 2024 RustFS Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use s3s::dto::{SelectObjectContentEventStream, SelectObjectContentOutput};
pub(crate) fn build_select_object_content_output(payload: SelectObjectContentEventStream) -> SelectObjectContentOutput {
SelectObjectContentOutput { payload: Some(payload) }
}
+25 -4
View File
@@ -12,7 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use s3s::dto::{DeleteObjectTaggingOutput, GetBucketTaggingOutput, GetObjectTaggingOutput, PutObjectTaggingOutput, Tag};
use s3s::dto::{
DeleteBucketTaggingOutput, DeleteObjectTaggingOutput, GetBucketTaggingOutput, GetObjectTaggingOutput, PutBucketTaggingOutput,
PutObjectTaggingOutput, Tag,
};
use s3s::{S3Error, S3ErrorCode, S3Result};
use std::collections::HashSet;
@@ -70,14 +73,23 @@ pub(crate) fn build_delete_object_tagging_output(version_id: Option<String>) ->
DeleteObjectTaggingOutput { version_id }
}
pub(crate) fn build_put_bucket_tagging_output() -> PutBucketTaggingOutput {
PutBucketTaggingOutput::default()
}
pub(crate) fn build_delete_bucket_tagging_output() -> DeleteBucketTaggingOutput {
DeleteBucketTaggingOutput {}
}
#[cfg(test)]
mod tests {
use super::{
build_delete_object_tagging_output, build_get_bucket_tagging_output, build_get_object_tagging_output,
build_put_object_tagging_output, validate_object_tag_set,
build_delete_bucket_tagging_output, build_delete_object_tagging_output, build_get_bucket_tagging_output,
build_get_object_tagging_output, build_put_bucket_tagging_output, build_put_object_tagging_output,
validate_object_tag_set,
};
use s3s::S3ErrorCode;
use s3s::dto::Tag;
use s3s::dto::{DeleteBucketTaggingOutput, Tag};
fn tag(key: Option<&str>, value: Option<&str>) -> Tag {
Tag {
@@ -163,4 +175,13 @@ mod tests {
assert_eq!(put_object_output.version_id, Some("vid-1".to_string()));
assert_eq!(delete_object_output.version_id, Some("vid-1".to_string()));
}
#[test]
fn test_build_bucket_tagging_outputs_are_default_shape() {
let put_output = build_put_bucket_tagging_output();
let delete_output = build_delete_bucket_tagging_output();
assert_eq!(put_output, Default::default());
assert_eq!(delete_output, DeleteBucketTaggingOutput {});
}
}