Files
rustfs/crates/s3-client/Cargo.toml
T
Zhengchao An 8f0d4a20d1 refactor(ecstore): extract the embedded S3 client into rustfs-s3-client (#6627)
The storage engine embedded a ~8.4K-line hand-written S3 HTTP client under crates/ecstore/src/client (rustfs/backlog#1842). That client is a legitimate engine capability — it consumes remote S3-compatible endpoints for ILM tier warm backends and transition targets — but it was misfiled inside the engine, dragging s3s/hyper wire types into ecstore and blocking ARCHITECTURE.md invariant 4.

This PR is the pure-move step: 21 modules move verbatim to the new crates/s3-client crate (rustfs-s3-client), and crates/ecstore/src/client/mod.rs becomes a re-export shim so every in-crate crate::client:: path keeps working. The two server-side modules that were historically misfiled under client/ — object_api_utils.rs and object_handlers_common.rs — stay in ecstore.

Three reverse dependencies from the client into engine internals are severed so the move can be pure:

- transition_api::ReaderImpl::ObjectBody held ecstore's GetObjectReader; the client only ever reads the body, so the variant now holds an ObjectReader newtype over Box<dyn AsyncRead + Send + Sync + Unpin> with the same read_all() surface. The single production construction site (set_disk transition upload) and the two engine-side consumers were adjusted.
- api_list/api_remove used ecstore's storage_api_contracts / object_api types; api_list now imports BucketInfo from rustfs-storage-api directly, and api_remove uses the client's own transition_api::ObjectInfo (only .name/.version_id were read; the error-path bucket name is now threaded as a parameter instead of read from the deleted objects).
- the api_put_object_streaming regression tests built a GetObjectReader by hand; they now wrap the duplex stream in ObjectReader::new.

Guard updates: the s3s footprint ratchet gains an ecstore-scoped counter (42 files, shrink-only, per rustfs/backlog#1842), the ecstore module-lint-blanket register follows the moved files into crates/s3-client so the blanket ratchet keeps covering them, the logging guardrail path pin follows transition_api.rs, and the ::other(format!) baseline is regenerated (moved call sites left ecstore).

Verification: cargo check -p rustfs-s3-client -p rustfs-ecstore; cargo nextest run -p rustfs-s3-client (43 passed) and -p rustfs-ecstore (4515/4523; the 8 failures reproduce identically on pristine origin/main on the same machine); cargo clippy --all-targets; scripts/check_layer_dependencies.sh, check_architecture_migration_rules.sh, check_s3s_footprint.sh, check_logging_guardrails.sh, check_error_other_format_ratchet.sh, check_doc_paths.sh, check_ci_paths_sync.sh all pass.
2026-08-26 12:38:52 +08:00

74 lines
3.0 KiB
TOML

# 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.
[package]
name = "rustfs-s3-client"
edition.workspace = true
license.workspace = true
repository.workspace = true
rust-version.workspace = true
version.workspace = true
homepage.workspace = true
description = "S3 client used by RustFS when the storage engine consumes remote S3-compatible endpoints (tier warm backends, transition targets)."
keywords = ["s3", "client", "tiering", "rustfs", "Minio"]
categories = ["web-programming", "development-tools", "network-programming"]
documentation = "https://docs.rs/rustfs-s3-client/latest/rustfs_s3_client/"
[dependencies]
rustfs-checksums.workspace = true
rustfs-config.workspace = true
rustfs-rio.workspace = true
rustfs-signer.workspace = true
rustfs-storage-api.workspace = true
rustfs-tls-runtime.workspace = true
rustfs-utils = { workspace = true, features = ["full"] }
base64-simd.workspace = true
bytes = { workspace = true, features = ["serde"] }
hex-simd = { workspace = true }
enumset = { workspace = true }
futures.workspace = true
futures-util.workspace = true
http.workspace = true
http-body = { workspace = true }
http-body-util.workspace = true
hyper = { workspace = true, features = ["http2", "http1", "server"] }
hyper-rustls = { workspace = true, default-features = false, features = ["native-tokio", "http1", "tls12", "logging", "http2", "aws-lc-rs"] }
hyper-util = { workspace = true, features = ["tokio", "server-auto", "server-graceful", "tracing"] }
lazy_static.workspace = true
md-5.workspace = true
quick-xml = { workspace = true, features = ["serialize", "async-tokio"] }
rand = { workspace = true, features = ["serde"] }
rustls = { workspace = true, default-features = false, features = ["aws-lc-rs", "logging", "tls12", "prefer-post-quantum", "std"] }
rustls-pki-types.workspace = true
s3s = { workspace = true, features = ["minio"] }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true, features = ["raw_value"] }
sha1 = { workspace = true }
sha2 = { workspace = true }
thiserror.workspace = true
time = { workspace = true, features = ["parsing", "formatting", "macros", "serde"] }
tokio = { workspace = true, features = ["io-util", "sync", "fs", "rt-multi-thread"] }
tokio-util = { workspace = true, features = ["io", "compat"] }
tower = { workspace = true, features = ["timeout"] }
tracing.workspace = true
url.workspace = true
urlencoding = { workspace = true }
uuid = { workspace = true, features = ["v4", "fast-rng", "serde", "macro-diagnostics"] }
[lints]
workspace = true
[lib]
doctest = false