Use TypedBuilder derive macro for S3 API request builders (#184)

Adopt the typed-builder crate throughout the S3 API to provide compile-time
validation of builder patterns. This change improves type safety and developer
experience when constructing S3 API requests.
This commit is contained in:
Henk-Jan Lebbink 2025-10-16 23:06:45 +02:00 committed by GitHub
parent 5a90956db8
commit e16d6d40cf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
204 changed files with 3513 additions and 3230 deletions

View File

@ -17,6 +17,7 @@ native-tls = ["reqwest/native-tls"]
rustls-tls = ["reqwest/rustls-tls"] rustls-tls = ["reqwest/rustls-tls"]
default-crypto = ["dep:sha2", "dep:hmac"] default-crypto = ["dep:sha2", "dep:hmac"]
ring = ["dep:ring"] ring = ["dep:ring"]
localhost = []
[workspace.dependencies] [workspace.dependencies]
uuid = "1.18" uuid = "1.18"
@ -33,41 +34,42 @@ bytes = { workspace = true }
async-std = { workspace = true, features = ["attributes"] } async-std = { workspace = true, features = ["attributes"] }
reqwest = { workspace = true, features = ["stream"] } reqwest = { workspace = true, features = ["stream"] }
async-recursion = "1.1.1" async-recursion = "1.1"
async-stream = "0.3.6" async-stream = "0.3"
async-trait = "0.1.88" async-trait = "0.1"
base64 = "0.22.1" base64 = "0.22"
chrono = "0.4.41" chrono = "0.4"
crc = "3.3.0" crc = "3.3"
dashmap = "6.1.0" dashmap = "6.1.0"
env_logger = "0.11.8" env_logger = "0.11"
hmac = { version = "0.12.1", optional = true } hmac = { version = "0.12", optional = true }
hyper = { version = "1.6.0", features = ["full"] } hyper = { version = "1.7", features = ["full"] }
lazy_static = "1.5.0" lazy_static = "1.5"
log = "0.4.27" log = "0.4"
md5 = "0.8.0" md5 = "0.8"
multimap = "0.10.1" multimap = "0.10"
percent-encoding = "2.3.1" percent-encoding = "2.3"
url = "2.5.4" url = "2.5"
regex = "1.11.1" regex = "1.12"
ring = { version = "0.17.14", optional = true, default-features = false, features = ["alloc"] } ring = { version = "0.17", optional = true, default-features = false, features = ["alloc"] }
serde = { version = "1.0.219", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.142" serde_json = "1.0"
sha2 = { version = "0.10.9", optional = true } sha2 = { version = "0.10", optional = true }
urlencoding = "2.1.3" urlencoding = "2.1"
xmltree = "0.11.0" xmltree = "0.11"
http = "1.3.1" http = "1.3"
thiserror = "2.0.14" thiserror = "2.0"
typed-builder = "0.22"
[dev-dependencies] [dev-dependencies]
minio-common = { path = "./common" } minio-common = { path = "./common" }
minio-macros = { path = "./macros" } minio-macros = { path = "./macros" }
tokio = { version = "1.47.1", features = ["full"] } tokio = { version = "1.48", features = ["full"] }
async-std = { version = "1.13.1", features = ["attributes", "tokio1"] } async-std = { version = "1.13", features = ["attributes", "tokio1"] }
clap = { version = "4.5.44", features = ["derive"] } clap = { version = "4.5", features = ["derive"] }
rand = { version = "0.9.2", features = ["small_rng"] } rand = { version = "0.9", features = ["small_rng"] }
quickcheck = "1.0.3" quickcheck = "1.0"
criterion = "0.7.0" criterion = "0.7"
[lib] [lib]
name = "minio" name = "minio"

View File

@ -18,13 +18,17 @@ All request builders implement the [`S3Api`] trait, which provides the async [`s
## Basic Usage ## Basic Usage
```no_run ```no_run
use minio::s3::Client; use minio::s3::MinioClient;
use minio::s3::creds::StaticProvider;
use minio::s3::http::BaseUrl;
use minio::s3::types::S3Api; use minio::s3::types::S3Api;
use minio::s3::response::BucketExistsResponse; use minio::s3::response::BucketExistsResponse;
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
let client: Client = Default::default(); // configure your client let base_url = "play.min.io".parse::<BaseUrl>().unwrap();
let static_provider = StaticProvider::new("Q3AM3UQ867SPQQA43P2F", "zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG", None);
let client = MinioClient::new(base_url, Some(static_provider), None, None).unwrap();
let exists: BucketExistsResponse = client let exists: BucketExistsResponse = client
.bucket_exists("my-bucket") .bucket_exists("my-bucket")
@ -46,7 +50,7 @@ async fn main() {
## Design ## Design
- Each API method on the [`Client`] returns a builder struct - Each API method on the [`MinioClient`] returns a builder struct
- Builders implement [`ToS3Request`] for request conversion and [`S3Api`] for execution - Builders implement [`ToS3Request`] for request conversion and [`S3Api`] for execution
- Responses implement [`FromS3Response`] for consistent deserialization - Responses implement [`FromS3Response`] for consistent deserialization

View File

@ -23,6 +23,11 @@ pub(crate) fn bench_bucket_exists(criterion: &mut Criterion) {
"bucket_exists", "bucket_exists",
criterion, criterion,
|| async { Ctx2::new().await }, || async { Ctx2::new().await },
|ctx| BucketExists::new(ctx.client.clone(), ctx.bucket.clone()), |ctx| {
BucketExists::builder()
.client(ctx.client.clone())
.bucket(ctx.bucket.clone())
.build()
},
); );
} }

View File

@ -27,8 +27,11 @@ pub(crate) fn bench_put_bucket_lifecycle(criterion: &mut Criterion) {
|| async { Ctx2::new().await }, || async { Ctx2::new().await },
|ctx| { |ctx| {
let config = create_bucket_lifecycle_config_examples(); let config = create_bucket_lifecycle_config_examples();
PutBucketLifecycle::new(ctx.client.clone(), ctx.bucket.clone()) PutBucketLifecycle::builder()
.client(ctx.client.clone())
.bucket(ctx.bucket.clone())
.life_cycle_config(config) .life_cycle_config(config)
.build()
}, },
) )
} }
@ -42,12 +45,18 @@ pub(crate) fn bench_get_bucket_lifecycle(criterion: &mut Criterion) {
ctx.client ctx.client
.put_bucket_lifecycle(&ctx.bucket) .put_bucket_lifecycle(&ctx.bucket)
.life_cycle_config(config) .life_cycle_config(config)
.build()
.send() .send()
.await .await
.unwrap(); .unwrap();
ctx ctx
}, },
|ctx| GetBucketLifecycle::new(ctx.client.clone(), ctx.bucket.clone()), |ctx| {
GetBucketLifecycle::builder()
.client(ctx.client.clone())
.bucket(ctx.bucket.clone())
.build()
},
) )
} }
pub(crate) fn bench_delete_bucket_lifecycle(criterion: &mut Criterion) { pub(crate) fn bench_delete_bucket_lifecycle(criterion: &mut Criterion) {
@ -55,6 +64,11 @@ pub(crate) fn bench_delete_bucket_lifecycle(criterion: &mut Criterion) {
"delete_bucket_lifecycle", "delete_bucket_lifecycle",
criterion, criterion,
|| async { Ctx2::new().await }, || async { Ctx2::new().await },
|ctx| DeleteBucketLifecycle::new(ctx.client.clone(), ctx.bucket.clone()), |ctx| {
DeleteBucketLifecycle::builder()
.client(ctx.client.clone())
.bucket(ctx.bucket.clone())
.build()
},
) )
} }

View File

@ -28,8 +28,11 @@ pub(crate) fn bench_put_bucket_notification(criterion: &mut Criterion) {
|| async { Ctx2::new().await }, || async { Ctx2::new().await },
|ctx| { |ctx| {
let config = create_bucket_notification_config_example(); let config = create_bucket_notification_config_example();
PutBucketNotification::new(ctx.client.clone(), ctx.bucket.clone()) PutBucketNotification::builder()
.client(ctx.client.clone())
.bucket(ctx.bucket.clone())
.notification_config(config) .notification_config(config)
.build()
}, },
) )
} }
@ -44,12 +47,18 @@ pub(crate) fn bench_get_bucket_notification(criterion: &mut Criterion) {
ctx.client ctx.client
.put_bucket_notification(&ctx.bucket) .put_bucket_notification(&ctx.bucket)
.notification_config(config) .notification_config(config)
.build()
.send() .send()
.await .await
.unwrap(); .unwrap();
ctx ctx
}, },
|ctx| GetBucketNotification::new(ctx.client.clone(), ctx.bucket.clone()), |ctx| {
GetBucketNotification::builder()
.client(ctx.client.clone())
.bucket(ctx.bucket.clone())
.build()
},
) )
} }
#[allow(dead_code)] #[allow(dead_code)]
@ -58,6 +67,11 @@ pub(crate) fn bench_delete_bucket_notification(criterion: &mut Criterion) {
"delete_bucket_notification", "delete_bucket_notification",
criterion, criterion,
|| async { Ctx2::new().await }, || async { Ctx2::new().await },
|ctx| DeleteBucketNotification::new(ctx.client.clone(), ctx.bucket.clone()), |ctx| {
DeleteBucketNotification::builder()
.client(ctx.client.clone())
.bucket(ctx.bucket.clone())
.build()
},
) )
} }

View File

@ -27,7 +27,11 @@ pub(crate) fn bench_put_bucket_policy(criterion: &mut Criterion) {
|| async { Ctx2::new().await }, || async { Ctx2::new().await },
|ctx| { |ctx| {
let config = create_bucket_policy_config_example(&ctx.bucket); let config = create_bucket_policy_config_example(&ctx.bucket);
PutBucketPolicy::new(ctx.client.clone(), ctx.bucket.clone()).config(config) PutBucketPolicy::builder()
.client(ctx.client.clone())
.bucket(ctx.bucket.clone())
.config(config)
.build()
}, },
) )
} }
@ -38,14 +42,22 @@ pub(crate) fn bench_get_bucket_policy(criterion: &mut Criterion) {
|| async { || async {
let ctx = Ctx2::new().await; let ctx = Ctx2::new().await;
let config = create_bucket_policy_config_example(&ctx.bucket); let config = create_bucket_policy_config_example(&ctx.bucket);
PutBucketPolicy::new(ctx.client.clone(), ctx.bucket.clone()) PutBucketPolicy::builder()
.client(ctx.client.clone())
.bucket(ctx.bucket.clone())
.config(config) .config(config)
.build()
.send() .send()
.await .await
.unwrap(); .unwrap();
ctx ctx
}, },
|ctx| GetBucketPolicy::new(ctx.client.clone(), ctx.bucket.clone()), |ctx| {
GetBucketPolicy::builder()
.client(ctx.client.clone())
.bucket(ctx.bucket.clone())
.build()
},
) )
} }
pub(crate) fn bench_delete_bucket_policy(criterion: &mut Criterion) { pub(crate) fn bench_delete_bucket_policy(criterion: &mut Criterion) {
@ -53,6 +65,11 @@ pub(crate) fn bench_delete_bucket_policy(criterion: &mut Criterion) {
"delete_bucket_policy", "delete_bucket_policy",
criterion, criterion,
|| async { Ctx2::new().await }, || async { Ctx2::new().await },
|ctx| DeleteBucketPolicy::new(ctx.client.clone(), ctx.bucket.clone()), |ctx| {
DeleteBucketPolicy::builder()
.client(ctx.client.clone())
.bucket(ctx.bucket.clone())
.build()
},
) )
} }

View File

@ -36,6 +36,7 @@ pub(crate) fn bench_put_bucket_replication(criterion: &mut Criterion) {
.client .client
.put_bucket_versioning(&ctx.bucket) .put_bucket_versioning(&ctx.bucket)
.versioning_status(VersioningStatus::Enabled) .versioning_status(VersioningStatus::Enabled)
.build()
.send() .send()
.await .await
.unwrap(); .unwrap();
@ -44,6 +45,7 @@ pub(crate) fn bench_put_bucket_replication(criterion: &mut Criterion) {
.client .client
.put_bucket_versioning(ctx.aux_bucket.clone().unwrap()) .put_bucket_versioning(ctx.aux_bucket.clone().unwrap())
.versioning_status(VersioningStatus::Enabled) .versioning_status(VersioningStatus::Enabled)
.build()
.send() .send()
.await .await
.unwrap(); .unwrap();
@ -53,8 +55,11 @@ pub(crate) fn bench_put_bucket_replication(criterion: &mut Criterion) {
|ctx| { |ctx| {
let config = let config =
create_bucket_replication_config_example(ctx.aux_bucket.clone().unwrap().as_str()); create_bucket_replication_config_example(ctx.aux_bucket.clone().unwrap().as_str());
PutBucketReplication::new(ctx.client.clone(), ctx.bucket.clone()) PutBucketReplication::builder()
.client(ctx.client.clone())
.bucket(ctx.bucket.clone())
.replication_config(config) .replication_config(config)
.build()
}, },
) )
} }
@ -71,6 +76,7 @@ pub(crate) fn bench_get_bucket_replication(criterion: &mut Criterion) {
.client .client
.put_bucket_versioning(&ctx.bucket) .put_bucket_versioning(&ctx.bucket)
.versioning_status(VersioningStatus::Enabled) .versioning_status(VersioningStatus::Enabled)
.build()
.send() .send()
.await .await
.unwrap(); .unwrap();
@ -79,13 +85,19 @@ pub(crate) fn bench_get_bucket_replication(criterion: &mut Criterion) {
.client .client
.put_bucket_versioning(ctx.aux_bucket.clone().unwrap()) .put_bucket_versioning(ctx.aux_bucket.clone().unwrap())
.versioning_status(VersioningStatus::Enabled) .versioning_status(VersioningStatus::Enabled)
.build()
.send() .send()
.await .await
.unwrap(); .unwrap();
ctx ctx
}, },
|ctx| GetBucketReplication::new(ctx.client.clone(), ctx.bucket.clone()), |ctx| {
GetBucketReplication::builder()
.client(ctx.client.clone())
.bucket(ctx.bucket.clone())
.build()
},
) )
} }
#[allow(dead_code)] #[allow(dead_code)]
@ -101,6 +113,7 @@ pub(crate) fn bench_delete_bucket_replication(criterion: &mut Criterion) {
.client .client
.put_bucket_versioning(&ctx.bucket) .put_bucket_versioning(&ctx.bucket)
.versioning_status(VersioningStatus::Enabled) .versioning_status(VersioningStatus::Enabled)
.build()
.send() .send()
.await .await
.unwrap(); .unwrap();
@ -109,12 +122,18 @@ pub(crate) fn bench_delete_bucket_replication(criterion: &mut Criterion) {
.client .client
.put_bucket_versioning(ctx.aux_bucket.clone().unwrap()) .put_bucket_versioning(ctx.aux_bucket.clone().unwrap())
.versioning_status(VersioningStatus::Enabled) .versioning_status(VersioningStatus::Enabled)
.build()
.send() .send()
.await .await
.unwrap(); .unwrap();
ctx ctx
}, },
|ctx| DeleteBucketReplication::new(ctx.client.clone(), ctx.bucket.clone()), |ctx| {
DeleteBucketReplication::builder()
.client(ctx.client.clone())
.bucket(ctx.bucket.clone())
.build()
},
) )
} }

View File

@ -29,8 +29,11 @@ pub(crate) async fn bench_put_bucket_tagging(criterion: &mut Criterion) {
criterion, criterion,
|| async { Ctx2::new().await }, || async { Ctx2::new().await },
|ctx| { |ctx| {
PutBucketTagging::new(ctx.client.clone(), ctx.bucket.clone()) PutBucketTagging::builder()
.client(ctx.client.clone())
.bucket(ctx.bucket.clone())
.tags(create_tags_example()) .tags(create_tags_example())
.build()
}, },
) )
} }
@ -46,12 +49,18 @@ pub(crate) async fn bench_get_bucket_tagging(criterion: &mut Criterion) {
ctx.client ctx.client
.put_bucket_tagging(&ctx.bucket) .put_bucket_tagging(&ctx.bucket)
.tags(create_tags_example()) .tags(create_tags_example())
.build()
.send() .send()
.await .await
.unwrap(); .unwrap();
ctx ctx
}, },
|ctx| GetBucketTagging::new(ctx.client.clone(), ctx.bucket.clone()), |ctx| {
GetBucketTagging::builder()
.client(ctx.client.clone())
.bucket(ctx.bucket.clone())
.build()
},
) )
} }
pub(crate) async fn bench_delete_bucket_tagging(criterion: &mut Criterion) { pub(crate) async fn bench_delete_bucket_tagging(criterion: &mut Criterion) {
@ -62,6 +71,11 @@ pub(crate) async fn bench_delete_bucket_tagging(criterion: &mut Criterion) {
"delete_bucket_tagging", "delete_bucket_tagging",
criterion, criterion,
|| async { Ctx2::new().await }, || async { Ctx2::new().await },
|ctx| DeleteBucketTagging::new(ctx.client.clone(), ctx.bucket.clone()), |ctx| {
DeleteBucketTagging::builder()
.client(ctx.client.clone())
.bucket(ctx.bucket.clone())
.build()
},
) )
} }

View File

@ -26,7 +26,12 @@ pub(crate) async fn bench_get_bucket_versioning(criterion: &mut Criterion) {
"get_bucket_versioning", "get_bucket_versioning",
criterion, criterion,
|| async { Ctx2::new().await }, || async { Ctx2::new().await },
|ctx| GetBucketVersioning::new(ctx.client.clone(), ctx.bucket.clone()), |ctx| {
GetBucketVersioning::builder()
.client(ctx.client.clone())
.bucket(ctx.bucket.clone())
.build()
},
) )
} }
pub(crate) async fn bench_put_bucket_versioning(criterion: &mut Criterion) { pub(crate) async fn bench_put_bucket_versioning(criterion: &mut Criterion) {
@ -38,8 +43,11 @@ pub(crate) async fn bench_put_bucket_versioning(criterion: &mut Criterion) {
criterion, criterion,
|| async { Ctx2::new().await }, || async { Ctx2::new().await },
|ctx| { |ctx| {
PutBucketVersioning::new(ctx.client.clone(), ctx.bucket.clone()) PutBucketVersioning::builder()
.client(ctx.client.clone())
.bucket(ctx.bucket.clone())
.versioning_status(VersioningStatus::Enabled) .versioning_status(VersioningStatus::Enabled)
.build()
}, },
) )
} }

View File

@ -23,6 +23,6 @@ pub(crate) fn bench_list_buckets(criterion: &mut Criterion) {
"list_buckets", "list_buckets",
criterion, criterion,
|| async { Ctx2::new().await }, || async { Ctx2::new().await },
|ctx| ListBuckets::new(ctx.client.clone()), |ctx| ListBuckets::builder().client(ctx.client.clone()).build(),
) )
} }

View File

@ -14,6 +14,7 @@
// limitations under the License. // limitations under the License.
use crate::common_benches::{Ctx2, benchmark_s3_api}; use crate::common_benches::{Ctx2, benchmark_s3_api};
use std::sync::Arc;
use criterion::Criterion; use criterion::Criterion;
use minio::s3::builders::AppendObject; use minio::s3::builders::AppendObject;
@ -41,18 +42,23 @@ pub(crate) async fn bench_object_append(criterion: &mut Criterion) {
let resp: StatObjectResponse = task::block_in_place(|| { let resp: StatObjectResponse = task::block_in_place(|| {
let runtime = let runtime =
tokio::runtime::Runtime::new().map_err(|e| Error::DriveIo(e.into()))?; tokio::runtime::Runtime::new().map_err(|e| Error::DriveIo(e.into()))?;
runtime.block_on(ctx.client.stat_object(&ctx.bucket, &ctx.object).send()) runtime.block_on(
ctx.client
.stat_object(&ctx.bucket, &ctx.object)
.build()
.send(),
)
}) })
.unwrap(); .unwrap();
let offset_bytes: u64 = resp.size().unwrap(); let offset_bytes: u64 = resp.size().unwrap();
AppendObject::new( AppendObject::builder()
ctx.client.clone(), .client(ctx.client.clone())
ctx.bucket.clone(), .bucket(ctx.bucket.clone())
ctx.object.clone(), .object(ctx.object.clone())
data1, .data(Arc::new(data1))
offset_bytes, .offset_bytes(offset_bytes)
) .build()
}, },
) )
} }

View File

@ -27,8 +27,17 @@ pub(crate) fn bench_object_copy_internal(criterion: &mut Criterion) {
|ctx| { |ctx| {
let object_name_src = &ctx.object; let object_name_src = &ctx.object;
let object_name_dst = rand_object_name(); let object_name_dst = rand_object_name();
CopyObjectInternal::new(ctx.client.clone(), ctx.bucket.clone(), object_name_dst) CopyObjectInternal::builder()
.source(CopySource::new(&ctx.bucket, object_name_src).unwrap()) .client(ctx.client.clone())
.bucket(ctx.bucket.clone())
.object(object_name_dst)
.source(
CopySource::builder()
.bucket(ctx.bucket.clone())
.object(object_name_src)
.build(),
)
.build()
}, },
) )
} }

View File

@ -28,8 +28,12 @@ pub(crate) async fn bench_put_object_legal_hold(criterion: &mut Criterion) {
criterion, criterion,
|| async { Ctx2::new_with_object(true).await }, || async { Ctx2::new_with_object(true).await },
|ctx| { |ctx| {
PutObjectLegalHold::new(ctx.client.clone(), ctx.bucket.clone(), ctx.object.clone()) PutObjectLegalHold::builder()
.legal_hold(Some(true)) .client(ctx.client.clone())
.bucket(ctx.bucket.clone())
.object(ctx.object.clone())
.legal_hold(true)
.build()
}, },
) )
} }
@ -44,11 +48,18 @@ pub(crate) async fn bench_get_object_legal_hold(criterion: &mut Criterion) {
let ctx = Ctx2::new_with_object(true).await; let ctx = Ctx2::new_with_object(true).await;
ctx.client ctx.client
.get_object_legal_hold(&ctx.bucket, &ctx.object) .get_object_legal_hold(&ctx.bucket, &ctx.object)
.build()
.send() .send()
.await .await
.unwrap(); .unwrap();
ctx ctx
}, },
|ctx| GetObjectLegalHold::new(ctx.client.clone(), ctx.bucket.clone(), ctx.object.clone()), |ctx| {
GetObjectLegalHold::builder()
.client(ctx.client.clone())
.bucket(ctx.bucket.clone())
.object(ctx.object.clone())
.build()
},
) )
} }

View File

@ -28,7 +28,11 @@ pub(crate) async fn bench_put_object_lock_config(criterion: &mut Criterion) {
|| async { Ctx2::new_with_object(true).await }, || async { Ctx2::new_with_object(true).await },
|ctx| { |ctx| {
let config = create_object_lock_config_example(); let config = create_object_lock_config_example();
PutObjectLockConfig::new(ctx.client.clone(), ctx.bucket.clone()).config(config) PutObjectLockConfig::builder()
.client(ctx.client.clone())
.bucket(ctx.bucket.clone())
.config(config)
.build()
}, },
) )
} }
@ -40,7 +44,12 @@ pub(crate) async fn bench_get_object_lock_config(criterion: &mut Criterion) {
"get_object_lock_config", "get_object_lock_config",
criterion, criterion,
|| async { Ctx2::new_with_object(true).await }, || async { Ctx2::new_with_object(true).await },
|ctx| GetObjectLockConfig::new(ctx.client.clone(), ctx.bucket.clone()), |ctx| {
GetObjectLockConfig::builder()
.client(ctx.client.clone())
.bucket(ctx.bucket.clone())
.build()
},
) )
} }
pub(crate) async fn bench_delete_object_lock_config(criterion: &mut Criterion) { pub(crate) async fn bench_delete_object_lock_config(criterion: &mut Criterion) {
@ -51,6 +60,11 @@ pub(crate) async fn bench_delete_object_lock_config(criterion: &mut Criterion) {
"delete_object_lock_config", "delete_object_lock_config",
criterion, criterion,
|| async { Ctx2::new_with_object(true).await }, || async { Ctx2::new_with_object(true).await },
|ctx| DeleteObjectLockConfig::new(ctx.client.clone(), ctx.bucket.clone()), |ctx| {
DeleteObjectLockConfig::builder()
.client(ctx.client.clone())
.bucket(ctx.bucket.clone())
.build()
},
) )
} }

View File

@ -14,9 +14,10 @@
// limitations under the License. // limitations under the License.
use crate::common_benches::{Ctx2, benchmark_s3_api}; use crate::common_benches::{Ctx2, benchmark_s3_api};
use std::sync::Arc;
use criterion::Criterion; use criterion::Criterion;
use minio::s3::builders::{ObjectContent, PutObject}; use minio::s3::builders::{ObjectContent, PutObject, UploadPart};
use minio::s3::segmented_bytes::SegmentedBytes; use minio::s3::segmented_bytes::SegmentedBytes;
use minio_common::rand_src::RandSrc; use minio_common::rand_src::RandSrc;
use minio_common::utils::rand_object_name; use minio_common::utils::rand_object_name;
@ -37,7 +38,16 @@ pub(crate) fn bench_object_put(criterion: &mut Criterion) {
}) })
.unwrap(); .unwrap();
PutObject::new(ctx.client.clone(), ctx.bucket.clone(), object_name, data) PutObject::builder()
.inner(
UploadPart::builder()
.client(ctx.client.clone())
.bucket(ctx.bucket.clone())
.object(object_name)
.data(Arc::new(data))
.build(),
)
.build()
}, },
) )
} }

View File

@ -30,9 +30,13 @@ pub(crate) async fn bench_put_object_retention(criterion: &mut Criterion) {
criterion, criterion,
|| async { Ctx2::new_with_object(true).await }, || async { Ctx2::new_with_object(true).await },
|ctx| { |ctx| {
PutObjectRetention::new(ctx.client.clone(), ctx.bucket.clone(), ctx.object.clone()) PutObjectRetention::builder()
.retention_mode(Some(RetentionMode::GOVERNANCE)) .client(ctx.client.clone())
.bucket(ctx.bucket.clone())
.object(ctx.object.clone())
.retention_mode(RetentionMode::GOVERNANCE)
.retain_until_date(Some(utc_now() + chrono::Duration::days(1))) .retain_until_date(Some(utc_now() + chrono::Duration::days(1)))
.build()
}, },
) )
} }
@ -45,15 +49,24 @@ pub(crate) async fn bench_get_object_retention(criterion: &mut Criterion) {
criterion, criterion,
|| async { || async {
let ctx = Ctx2::new_with_object(true).await; let ctx = Ctx2::new_with_object(true).await;
let _resp: PutObjectRetentionResponse = let _resp: PutObjectRetentionResponse = PutObjectRetention::builder()
PutObjectRetention::new(ctx.client.clone(), ctx.bucket.clone(), ctx.object.clone()) .client(ctx.client.clone())
.retention_mode(Some(RetentionMode::GOVERNANCE)) .bucket(ctx.bucket.clone())
.retain_until_date(Some(utc_now() + chrono::Duration::days(1))) .object(ctx.object.clone())
.send() .retention_mode(RetentionMode::GOVERNANCE)
.await .retain_until_date(Some(utc_now() + chrono::Duration::days(1)))
.unwrap(); .build()
.send()
.await
.unwrap();
ctx ctx
}, },
|ctx| GetObjectRetention::new(ctx.client.clone(), ctx.bucket.clone(), ctx.object.clone()), |ctx| {
GetObjectRetention::builder()
.client(ctx.client.clone())
.bucket(ctx.bucket.clone())
.object(ctx.object.clone())
.build()
},
) )
} }

View File

@ -30,8 +30,12 @@ pub(crate) async fn bench_put_object_tagging(criterion: &mut Criterion) {
criterion, criterion,
|| async { Ctx2::new_with_object(false).await }, || async { Ctx2::new_with_object(false).await },
|ctx| { |ctx| {
PutObjectTagging::new(ctx.client.clone(), ctx.bucket.clone(), ctx.object.clone()) PutObjectTagging::builder()
.client(ctx.client.clone())
.bucket(ctx.bucket.clone())
.object(ctx.object.clone())
.tags(create_tags_example()) .tags(create_tags_example())
.build()
}, },
) )
} }
@ -49,11 +53,18 @@ pub(crate) async fn bench_get_object_tagging(criterion: &mut Criterion) {
.client .client
.put_object_tagging(&ctx.bucket, &ctx.object) .put_object_tagging(&ctx.bucket, &ctx.object)
.tags(create_tags_example()) .tags(create_tags_example())
.build()
.send() .send()
.await .await
.unwrap(); .unwrap();
ctx ctx
}, },
|ctx| GetObjectTagging::new(ctx.client.clone(), ctx.bucket.clone(), ctx.object.clone()), |ctx| {
GetObjectTagging::builder()
.client(ctx.client.clone())
.bucket(ctx.bucket.clone())
.object(ctx.object.clone())
.build()
},
) )
} }

View File

@ -14,7 +14,7 @@
// limitations under the License. // limitations under the License.
use criterion::Criterion; use criterion::Criterion;
use minio::s3::Client; use minio::s3::MinioClient;
use minio::s3::error::Error; use minio::s3::error::Error;
use minio::s3::response::{CreateBucketResponse, PutObjectContentResponse}; use minio::s3::response::{CreateBucketResponse, PutObjectContentResponse};
use minio::s3::types::{FromS3Response, S3Api, S3Request}; use minio::s3::types::{FromS3Response, S3Api, S3Request};
@ -27,7 +27,7 @@ use std::env;
use tokio::runtime::Runtime; use tokio::runtime::Runtime;
pub(crate) struct Ctx2 { pub(crate) struct Ctx2 {
pub client: Client, pub client: MinioClient,
pub bucket: String, pub bucket: String,
pub object: String, pub object: String,
_cleanup: CleanupGuard, _cleanup: CleanupGuard,
@ -64,6 +64,7 @@ impl Ctx2 {
.client .client
.create_bucket(&bucket_name) .create_bucket(&bucket_name)
.object_lock(object_lock) .object_lock(object_lock)
.build()
.send() .send()
.await .await
.unwrap(); .unwrap();
@ -73,6 +74,7 @@ impl Ctx2 {
let _resp: PutObjectContentResponse = ctx let _resp: PutObjectContentResponse = ctx
.client .client
.put_object_content(&bucket_name, &object_name, data) .put_object_content(&bucket_name, &object_name, data)
.build()
.send() .send()
.await .await
.unwrap(); .unwrap();
@ -95,6 +97,7 @@ impl Ctx2 {
.client .client
.create_bucket(&bucket_name) .create_bucket(&bucket_name)
.object_lock(false) .object_lock(false)
.build()
.send() .send()
.await .await
.unwrap(); .unwrap();

View File

@ -13,17 +13,17 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use minio::s3::Client; use minio::s3::MinioClient;
/// Cleanup guard that removes the bucket when it is dropped /// Cleanup guard that removes the bucket when it is dropped
pub struct CleanupGuard { pub struct CleanupGuard {
client: Client, client: MinioClient,
bucket_name: String, bucket_name: String,
} }
impl CleanupGuard { impl CleanupGuard {
#[allow(dead_code)] #[allow(dead_code)]
pub fn new<S: Into<String>>(client: Client, bucket_name: S) -> Self { pub fn new<S: Into<String>>(client: MinioClient, bucket_name: S) -> Self {
Self { Self {
client, client,
bucket_name: bucket_name.into(), bucket_name: bucket_name.into(),
@ -35,7 +35,7 @@ impl CleanupGuard {
} }
} }
pub async fn cleanup(client: Client, bucket_name: &str) { pub async fn cleanup(client: MinioClient, bucket_name: &str) {
tokio::select!( tokio::select!(
_ = tokio::time::sleep(std::time::Duration::from_secs(60)) => { _ = tokio::time::sleep(std::time::Duration::from_secs(60)) => {
eprintln!("Cleanup timeout after 60s while removing bucket {bucket_name}"); eprintln!("Cleanup timeout after 60s while removing bucket {bucket_name}");

View File

@ -15,7 +15,7 @@
use crate::cleanup_guard::CleanupGuard; use crate::cleanup_guard::CleanupGuard;
use crate::utils::rand_bucket_name; use crate::utils::rand_bucket_name;
use minio::s3::Client; use minio::s3::MinioClient;
use minio::s3::creds::StaticProvider; use minio::s3::creds::StaticProvider;
use minio::s3::http::BaseUrl; use minio::s3::http::BaseUrl;
use minio::s3::types::S3Api; use minio::s3::types::S3Api;
@ -23,7 +23,7 @@ use std::path::{Path, PathBuf};
#[derive(Clone)] #[derive(Clone)]
pub struct TestContext { pub struct TestContext {
pub client: Client, pub client: MinioClient,
pub base_url: BaseUrl, pub base_url: BaseUrl,
pub access_key: String, pub access_key: String,
pub secret_key: String, pub secret_key: String,
@ -57,7 +57,7 @@ impl TestContext {
} }
let static_provider = StaticProvider::new(&access_key, &secret_key, None); let static_provider = StaticProvider::new(&access_key, &secret_key, None);
let client = Client::new( let client = MinioClient::new(
base_url.clone(), base_url.clone(),
Some(static_provider), Some(static_provider),
ssl_cert_file, ssl_cert_file,
@ -114,7 +114,7 @@ impl TestContext {
base_url.region = region; base_url.region = region;
let static_provider = StaticProvider::new(&access_key, &secret_key, None); let static_provider = StaticProvider::new(&access_key, &secret_key, None);
let client = Client::new( let client = MinioClient::new(
base_url.clone(), base_url.clone(),
Some(static_provider), Some(static_provider),
Some(&*ssl_cert_file), Some(&*ssl_cert_file),
@ -154,6 +154,7 @@ impl TestContext {
let _resp = self let _resp = self
.client .client
.create_bucket(&bucket_name) .create_bucket(&bucket_name)
.build()
.send() .send()
.await .await
.unwrap(); .unwrap();

View File

@ -15,8 +15,10 @@
mod common; mod common;
use crate::common::{create_bucket_if_not_exists, create_client_on_localhost}; use crate::common::create_bucket_if_not_exists;
use minio::s3::Client; use minio::s3::MinioClient;
use minio::s3::creds::StaticProvider;
use minio::s3::http::BaseUrl;
use minio::s3::response::a_response_traits::HasObjectSize; use minio::s3::response::a_response_traits::HasObjectSize;
use minio::s3::response::{AppendObjectResponse, StatObjectResponse}; use minio::s3::response::{AppendObjectResponse, StatObjectResponse};
use minio::s3::segmented_bytes::SegmentedBytes; use minio::s3::segmented_bytes::SegmentedBytes;
@ -27,7 +29,10 @@ use rand::distr::Alphanumeric;
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> { async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
env_logger::init(); // Note: set environment variable RUST_LOG="INFO" to log info and higher env_logger::init(); // Note: set environment variable RUST_LOG="INFO" to log info and higher
let client: Client = create_client_on_localhost()?;
let base_url = "http://localhost:9000/".parse::<BaseUrl>()?;
let static_provider = StaticProvider::new("minioadmin", "minioadmin", None);
let client = MinioClient::new(base_url, Some(static_provider), None, None)?;
if !client.is_minio_express().await { if !client.is_minio_express().await {
println!("Need (MinIO) Express mode to run this example"); println!("Need (MinIO) Express mode to run this example");
@ -51,6 +56,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let resp: AppendObjectResponse = client let resp: AppendObjectResponse = client
.append_object(bucket_name, object_name, data, offset_bytes) .append_object(bucket_name, object_name, data, offset_bytes)
.build()
.send() .send()
.await?; .await?;
@ -63,7 +69,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
} }
//println!("Append response: {resp:#?}"); //println!("Append response: {resp:#?}");
let resp: StatObjectResponse = client.stat_object(bucket_name, object_name).send().await?; let resp: StatObjectResponse = client
.stat_object(bucket_name, object_name)
.build()
.send()
.await?;
if resp.size()? != offset_bytes { if resp.size()? != offset_bytes {
panic!( panic!(
"from the stat_Object: size mismatch: expected {}, got {offset_bytes}", "from the stat_Object: size mismatch: expected {}, got {offset_bytes}",

View File

@ -16,20 +16,23 @@
mod common; mod common;
use crate::common::{create_bucket_if_not_exists, create_client_on_play}; use crate::common::{create_bucket_if_not_exists, create_client_on_play};
use minio::s3::Client; use minio::s3::MinioClient;
use minio::s3::response::{GetBucketEncryptionResponse, PutBucketEncryptionResponse}; use minio::s3::response::{GetBucketEncryptionResponse, PutBucketEncryptionResponse};
use minio::s3::types::{S3Api, SseConfig}; use minio::s3::types::{S3Api, SseConfig};
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> { async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
env_logger::init(); // Note: set environment variable RUST_LOG="INFO" to log info and higher env_logger::init(); // Note: set environment variable RUST_LOG="INFO" to log info and higher
let client: Client = create_client_on_play()?; let client: MinioClient = create_client_on_play()?;
let bucket_name: &str = "encryption-rust-bucket"; let bucket_name: &str = "encryption-rust-bucket";
create_bucket_if_not_exists(bucket_name, &client).await?; create_bucket_if_not_exists(bucket_name, &client).await?;
let resp: GetBucketEncryptionResponse = let resp: GetBucketEncryptionResponse = client
client.get_bucket_encryption(bucket_name).send().await?; .get_bucket_encryption(bucket_name)
.build()
.send()
.await?;
log::info!("encryption before: config={:?}", resp.config()); log::info!("encryption before: config={:?}", resp.config());
let config = SseConfig::default(); let config = SseConfig::default();
@ -38,11 +41,15 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let _resp: PutBucketEncryptionResponse = client let _resp: PutBucketEncryptionResponse = client
.put_bucket_encryption(bucket_name) .put_bucket_encryption(bucket_name)
.sse_config(config.clone()) .sse_config(config.clone())
.build()
.send() .send()
.await?; .await?;
let resp: GetBucketEncryptionResponse = let resp: GetBucketEncryptionResponse = client
client.get_bucket_encryption(bucket_name).send().await?; .get_bucket_encryption(bucket_name)
.build()
.send()
.await?;
log::info!("encryption after: config={:?}", resp.config()); log::info!("encryption after: config={:?}", resp.config());
Ok(()) Ok(())

View File

@ -16,7 +16,7 @@
mod common; mod common;
use crate::common::{create_bucket_if_not_exists, create_client_on_play}; use crate::common::{create_bucket_if_not_exists, create_client_on_play};
use minio::s3::Client; use minio::s3::MinioClient;
use minio::s3::lifecycle_config::{LifecycleConfig, LifecycleRule}; use minio::s3::lifecycle_config::{LifecycleConfig, LifecycleRule};
use minio::s3::response::{ use minio::s3::response::{
DeleteBucketLifecycleResponse, GetBucketLifecycleResponse, PutBucketLifecycleResponse, DeleteBucketLifecycleResponse, GetBucketLifecycleResponse, PutBucketLifecycleResponse,
@ -26,15 +26,18 @@ use minio::s3::types::{Filter, S3Api};
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> { async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
env_logger::init(); // Note: set environment variable RUST_LOG="INFO" to log info and higher env_logger::init(); // Note: set environment variable RUST_LOG="INFO" to log info and higher
let client: Client = create_client_on_play()?; let client: MinioClient = create_client_on_play()?;
let bucket_name: &str = "lifecycle-rust-bucket"; let bucket_name: &str = "lifecycle-rust-bucket";
create_bucket_if_not_exists(bucket_name, &client).await?; create_bucket_if_not_exists(bucket_name, &client).await?;
if false { if false {
// TODO // TODO
let resp: GetBucketLifecycleResponse = let resp: GetBucketLifecycleResponse = client
client.get_bucket_lifecycle(bucket_name).send().await?; .get_bucket_lifecycle(bucket_name)
.build()
.send()
.await?;
log::info!("life cycle settings before setting: resp={resp:?}"); log::info!("life cycle settings before setting: resp={resp:?}");
} }
@ -52,21 +55,28 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let resp: PutBucketLifecycleResponse = client let resp: PutBucketLifecycleResponse = client
.put_bucket_lifecycle(bucket_name) .put_bucket_lifecycle(bucket_name)
.life_cycle_config(LifecycleConfig { rules }) .life_cycle_config(LifecycleConfig { rules })
.build()
.send() .send()
.await?; .await?;
log::info!("response of setting life cycle config: resp={resp:?}"); log::info!("response of setting life cycle config: resp={resp:?}");
if false { if false {
// TODO // TODO
let resp: GetBucketLifecycleResponse = let resp: GetBucketLifecycleResponse = client
client.get_bucket_lifecycle(bucket_name).send().await?; .get_bucket_lifecycle(bucket_name)
.build()
.send()
.await?;
log::info!("life cycle settings after setting: resp={resp:?}"); log::info!("life cycle settings after setting: resp={resp:?}");
} }
if false { if false {
// TODO // TODO
let resp: DeleteBucketLifecycleResponse = let resp: DeleteBucketLifecycleResponse = client
client.delete_bucket_lifecycle(bucket_name).send().await?; .delete_bucket_lifecycle(bucket_name)
.build()
.send()
.await?;
log::info!("response of deleting lifecycle config: resp={resp:?}"); log::info!("response of deleting lifecycle config: resp={resp:?}");
} }
Ok(()) Ok(())

View File

@ -16,7 +16,7 @@
mod common; mod common;
use crate::common::{create_bucket_if_not_exists, create_client_on_play}; use crate::common::{create_bucket_if_not_exists, create_client_on_play};
use minio::s3::Client; use minio::s3::MinioClient;
use minio::s3::builders::VersioningStatus; use minio::s3::builders::VersioningStatus;
use minio::s3::response::{GetBucketVersioningResponse, PutBucketVersioningResponse}; use minio::s3::response::{GetBucketVersioningResponse, PutBucketVersioningResponse};
use minio::s3::types::S3Api; use minio::s3::types::S3Api;
@ -24,13 +24,16 @@ use minio::s3::types::S3Api;
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> { async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
env_logger::init(); // Note: set environment variable RUST_LOG="INFO" to log info and higher env_logger::init(); // Note: set environment variable RUST_LOG="INFO" to log info and higher
let client: Client = create_client_on_play()?; let client: MinioClient = create_client_on_play()?;
let bucket_name: &str = "versioning-rust-bucket"; let bucket_name: &str = "versioning-rust-bucket";
create_bucket_if_not_exists(bucket_name, &client).await?; create_bucket_if_not_exists(bucket_name, &client).await?;
let resp: GetBucketVersioningResponse = let resp: GetBucketVersioningResponse = client
client.get_bucket_versioning(bucket_name).send().await?; .get_bucket_versioning(bucket_name)
.build()
.send()
.await?;
log::info!( log::info!(
"versioning before: status={:?}, mfa_delete={:?}", "versioning before: status={:?}, mfa_delete={:?}",
resp.status(), resp.status(),
@ -40,11 +43,15 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let _resp: PutBucketVersioningResponse = client let _resp: PutBucketVersioningResponse = client
.put_bucket_versioning(bucket_name) .put_bucket_versioning(bucket_name)
.versioning_status(VersioningStatus::Enabled) .versioning_status(VersioningStatus::Enabled)
.build()
.send() .send()
.await?; .await?;
let resp: GetBucketVersioningResponse = let resp: GetBucketVersioningResponse = client
client.get_bucket_versioning(bucket_name).send().await?; .get_bucket_versioning(bucket_name)
.build()
.send()
.await?;
log::info!( log::info!(
"versioning after setting to Enabled: status={:?}, mfa_delete={:?}", "versioning after setting to Enabled: status={:?}, mfa_delete={:?}",
@ -55,11 +62,15 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let _resp: PutBucketVersioningResponse = client let _resp: PutBucketVersioningResponse = client
.put_bucket_versioning(bucket_name) .put_bucket_versioning(bucket_name)
.versioning_status(VersioningStatus::Suspended) .versioning_status(VersioningStatus::Suspended)
.build()
.send() .send()
.await?; .await?;
let resp: GetBucketVersioningResponse = let resp: GetBucketVersioningResponse = client
client.get_bucket_versioning(bucket_name).send().await?; .get_bucket_versioning(bucket_name)
.build()
.send()
.await?;
log::info!( log::info!(
"versioning after setting to Suspended: status={:?}, mfa_delete={:?}", "versioning after setting to Suspended: status={:?}, mfa_delete={:?}",
@ -70,11 +81,15 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let _resp: PutBucketVersioningResponse = client let _resp: PutBucketVersioningResponse = client
.put_bucket_versioning(bucket_name) .put_bucket_versioning(bucket_name)
//.versioning_status(VersioningStatus::Suspended) //.versioning_status(VersioningStatus::Suspended)
.build()
.send() .send()
.await?; .await?;
let resp: GetBucketVersioningResponse = let resp: GetBucketVersioningResponse = client
client.get_bucket_versioning(bucket_name).send().await?; .get_bucket_versioning(bucket_name)
.build()
.send()
.await?;
log::info!( log::info!(
"versioning after setting to None: status={:?}, mfa_delete={:?}", "versioning after setting to None: status={:?}, mfa_delete={:?}",

View File

@ -1,11 +1,26 @@
// MinIO Rust Library for Amazon S3 Compatible Cloud Storage
// Copyright 2025 MinIO, Inc.
//
// 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 minio::s3::creds::StaticProvider; use minio::s3::creds::StaticProvider;
use minio::s3::http::BaseUrl; use minio::s3::http::BaseUrl;
use minio::s3::response::BucketExistsResponse; use minio::s3::response::BucketExistsResponse;
use minio::s3::types::S3Api; use minio::s3::types::S3Api;
use minio::s3::{Client, ClientBuilder}; use minio::s3::{MinioClient, MinioClientBuilder};
#[allow(dead_code)] #[allow(dead_code)]
pub fn create_client_on_play() -> Result<Client, Box<dyn std::error::Error + Send + Sync>> { pub fn create_client_on_play() -> Result<MinioClient, Box<dyn std::error::Error + Send + Sync>> {
let base_url = "https://play.min.io".parse::<BaseUrl>()?; let base_url = "https://play.min.io".parse::<BaseUrl>()?;
log::info!("Trying to connect to MinIO at: `{base_url:?}`"); log::info!("Trying to connect to MinIO at: `{base_url:?}`");
@ -15,20 +30,7 @@ pub fn create_client_on_play() -> Result<Client, Box<dyn std::error::Error + Sen
None, None,
); );
let client = ClientBuilder::new(base_url.clone()) let client = MinioClientBuilder::new(base_url.clone())
.provider(Some(static_provider))
.build()?;
Ok(client)
}
#[allow(dead_code)]
pub fn create_client_on_localhost() -> Result<Client, Box<dyn std::error::Error + Send + Sync>> {
let base_url = "http://localhost:9000/".parse::<BaseUrl>()?;
log::info!("Trying to connect to MinIO at: `{base_url:?}`");
let static_provider = StaticProvider::new("minioadmin", "minioadmin", None);
let client = ClientBuilder::new(base_url.clone())
.provider(Some(static_provider)) .provider(Some(static_provider))
.build()?; .build()?;
Ok(client) Ok(client)
@ -36,14 +38,14 @@ pub fn create_client_on_localhost() -> Result<Client, Box<dyn std::error::Error
pub async fn create_bucket_if_not_exists( pub async fn create_bucket_if_not_exists(
bucket_name: &str, bucket_name: &str,
client: &Client, client: &MinioClient,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> { ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
// Check 'bucket_name' bucket exist or not. // Check 'bucket_name' bucket exist or not.
let resp: BucketExistsResponse = client.bucket_exists(bucket_name).send().await?; let resp: BucketExistsResponse = client.bucket_exists(bucket_name).build().send().await?;
// Make 'bucket_name' bucket if not exist. // Make 'bucket_name' bucket if not exist.
if !resp.exists() { if !resp.exists() {
client.create_bucket(bucket_name).send().await.unwrap(); client.create_bucket(bucket_name).build().send().await?;
}; };
Ok(()) Ok(())
} }

View File

@ -16,7 +16,7 @@
mod common; mod common;
use crate::common::{create_bucket_if_not_exists, create_client_on_play}; use crate::common::{create_bucket_if_not_exists, create_client_on_play};
use minio::s3::Client; use minio::s3::MinioClient;
use minio::s3::builders::ObjectContent; use minio::s3::builders::ObjectContent;
use minio::s3::types::S3Api; use minio::s3::types::S3Api;
use std::path::Path; use std::path::Path;
@ -24,7 +24,7 @@ use std::path::Path;
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> { async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
env_logger::init(); // Note: set environment variable RUST_LOG="INFO" to log info and higher env_logger::init(); // Note: set environment variable RUST_LOG="INFO" to log info and higher
let client: Client = create_client_on_play()?; let client: MinioClient = create_client_on_play()?;
let bucket_name: &str = "file-download-rust-bucket"; let bucket_name: &str = "file-download-rust-bucket";
let object_name: &str = "cat.png"; let object_name: &str = "cat.png";
@ -45,6 +45,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let content = ObjectContent::from(filename); let content = ObjectContent::from(filename);
client client
.put_object_content(bucket_name, object_name, content) .put_object_content(bucket_name, object_name, content)
.build()
.send() .send()
.await?; .await?;
@ -53,7 +54,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
filename.display() filename.display()
); );
let get_object = client.get_object(bucket_name, object_name).send().await?; let get_object = client
.get_object(bucket_name, object_name)
.build()
.send()
.await?;
get_object get_object
.content()? .content()?

View File

@ -15,14 +15,14 @@
mod common; mod common;
use crate::common::{create_bucket_if_not_exists, create_client_on_play}; use crate::common::{create_bucket_if_not_exists, create_client_on_play};
use minio::s3::Client; use minio::s3::MinioClient;
use minio::s3::builders::ObjectContent; use minio::s3::builders::ObjectContent;
use std::path::Path; use std::path::Path;
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> { async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
env_logger::init(); // Note: set environment variable RUST_LOG="INFO" to log info and higher env_logger::init(); // Note: set environment variable RUST_LOG="INFO" to log info and higher
let client: Client = create_client_on_play()?; let client: MinioClient = create_client_on_play()?;
let bucket_name: &str = "file-upload-rust-bucket"; let bucket_name: &str = "file-upload-rust-bucket";
create_bucket_if_not_exists(bucket_name, &client).await?; create_bucket_if_not_exists(bucket_name, &client).await?;
@ -43,6 +43,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let content = ObjectContent::from(filename); let content = ObjectContent::from(filename);
client client
.put_object_content(bucket_name, object_name, content) .put_object_content(bucket_name, object_name, content)
.build()
.send() .send()
.await?; .await?;

View File

@ -16,8 +16,8 @@
mod common; mod common;
use crate::common::create_bucket_if_not_exists; use crate::common::create_bucket_if_not_exists;
use minio::s3::MinioClientBuilder;
use minio::s3::builders::ObjectContent; use minio::s3::builders::ObjectContent;
use minio::s3::client::ClientBuilder;
use minio::s3::creds::StaticProvider; use minio::s3::creds::StaticProvider;
use minio::s3::http::BaseUrl; use minio::s3::http::BaseUrl;
use minio::s3::response::GetObjectPromptResponse; use minio::s3::response::GetObjectPromptResponse;
@ -34,7 +34,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let static_provider = StaticProvider::new("admin", "admin", None); let static_provider = StaticProvider::new("admin", "admin", None);
let client = ClientBuilder::new(base_url.clone()) let client = MinioClientBuilder::new(base_url.clone())
.provider(Some(static_provider)) .provider(Some(static_provider))
.ignore_cert_check(Some(true)) .ignore_cert_check(Some(true))
.build()?; .build()?;
@ -58,6 +58,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let content = ObjectContent::from(filename); let content = ObjectContent::from(filename);
client client
.put_object_content(bucket_name, object_name, content) .put_object_content(bucket_name, object_name, content)
.build()
.send() .send()
.await?; .await?;
@ -69,6 +70,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let resp: GetObjectPromptResponse = client let resp: GetObjectPromptResponse = client
.get_object_prompt(bucket_name, object_name, "what is it about?") .get_object_prompt(bucket_name, object_name, "what is it about?")
//.lambda_arn("arn:minio:s3-object-lambda::_:webhook") // this is the default value //.lambda_arn("arn:minio:s3-object-lambda::_:webhook") // this is the default value
.build()
.send() .send()
.await?; .await?;

View File

@ -17,7 +17,7 @@ use clap::Parser;
use log::info; use log::info;
use minio::s3::response::BucketExistsResponse; use minio::s3::response::BucketExistsResponse;
use minio::s3::types::S3Api; use minio::s3::types::S3Api;
use minio::s3::{Client, builders::ObjectContent, client::ClientBuilder, creds::StaticProvider}; use minio::s3::{MinioClient, MinioClientBuilder, builders::ObjectContent, creds::StaticProvider};
use std::path::PathBuf; use std::path::PathBuf;
/// Upload a file to the given bucket and object path on the MinIO Play server. /// Upload a file to the given bucket and object path on the MinIO Play server.
@ -41,20 +41,21 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
None, None,
); );
let client: Client = ClientBuilder::new("https://play.min.io".parse()?) let client: MinioClient = MinioClientBuilder::new("https://play.min.io".parse()?)
.provider(Some(static_provider)) .provider(Some(static_provider))
.build()?; .build()?;
let resp: BucketExistsResponse = client.bucket_exists(&args.bucket).send().await.unwrap(); let resp: BucketExistsResponse = client.bucket_exists(&args.bucket).build().send().await?;
if !resp.exists() { if !resp.exists() {
client.create_bucket(&args.bucket).send().await.unwrap(); client.create_bucket(&args.bucket).build().send().await?;
} }
let content = ObjectContent::from(args.file.as_path()); let content = ObjectContent::from(args.file.as_path());
// Put an object // Put an object
client client
.put_object_content(&args.bucket, &args.object, content) .put_object_content(&args.bucket, &args.object, content)
.build()
.send() .send()
.await?; .await?;

View File

@ -71,7 +71,7 @@ impl MacroArgs {
if let Some(FnArg::Typed(pat_type)) = iter.next() { if let Some(FnArg::Typed(pat_type)) = iter.next() {
let type_str = pat_type.ty.to_token_stream().to_string(); let type_str = pat_type.ty.to_token_stream().to_string();
if !type_str.contains("TestContext") { if !type_str.contains("TestContext") {
let error_msg = "First argument must be of type TestContext"; let error_msg = "The first argument must be of type TestContext";
return Err(proc_macro::TokenStream::from( return Err(proc_macro::TokenStream::from(
Error::custom(error_msg) Error::custom(error_msg)
.with_span(&pat_type.span()) .with_span(&pat_type.span())
@ -86,7 +86,7 @@ impl MacroArgs {
{ {
let type_str = pat_type.ty.to_token_stream().to_string(); let type_str = pat_type.ty.to_token_stream().to_string();
if !type_str.contains("String") { if !type_str.contains("String") {
let error_msg = "Second argument must be of type String"; let error_msg = "The second argument must be of type String";
return Err(proc_macro::TokenStream::from( return Err(proc_macro::TokenStream::from(
Error::custom(error_msg) Error::custom(error_msg)
.with_span(&pat_type.span()) .with_span(&pat_type.span())
@ -261,7 +261,7 @@ fn generate_with_bucket_body(
let client_clone = ctx.client.clone(); let client_clone = ctx.client.clone();
let bucket_name = #bucket_name; let bucket_name = #bucket_name;
let resp = client_clone.create_bucket(bucket_name)#maybe_lock.send().await.expect("Failed to create bucket"); let resp = client_clone.create_bucket(bucket_name)#maybe_lock.build().send().await.expect("Failed to create bucket");
assert_eq!(resp.bucket(), bucket_name); assert_eq!(resp.bucket(), bucket_name);
let res = AssertUnwindSafe(#inner_fn_name(ctx, resp.bucket().to_string())).catch_unwind().await; let res = AssertUnwindSafe(#inner_fn_name(ctx, resp.bucket().to_string())).catch_unwind().await;
#maybe_cleanup #maybe_cleanup

View File

@ -26,16 +26,21 @@
//! ## Basic Usage //! ## Basic Usage
//! //!
//! ```no_run //! ```no_run
//! use minio::s3::Client; //! use minio::s3::MinioClient;
//! use minio::s3::creds::StaticProvider;
//! use minio::s3::http::BaseUrl;
//! use minio::s3::types::S3Api; //! use minio::s3::types::S3Api;
//! use minio::s3::response::BucketExistsResponse; //! use minio::s3::response::BucketExistsResponse;
//! //!
//! #[tokio::main] //! #[tokio::main]
//! async fn main() { //! async fn main() {
//! let client: Client = Default::default(); // configure your client //! let base_url = "play.min.io".parse::<BaseUrl>().unwrap();
//! let static_provider = StaticProvider::new("Q3AM3UQ867SPQQA43P2F", "zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG", None);
//! let client = MinioClient::new(base_url, Some(static_provider), None, None).unwrap();
//! //!
//! let exists: BucketExistsResponse = client //! let exists: BucketExistsResponse = client
//! .bucket_exists("my-bucket") //! .bucket_exists("my-bucket")
//! .build()
//! .send() //! .send()
//! .await //! .await
//! .expect("request failed"); //! .expect("request failed");
@ -51,7 +56,7 @@
//! - Transparent error handling via `Result<T, Error>` //! - Transparent error handling via `Result<T, Error>`
//! //!
//! ## Design //! ## Design
//! - Each API method on the [`s3::client::Client`] returns a builder struct //! - Each API method on the [`s3::client::MinioClient`] returns a builder struct
//! - Builders implement [`s3::types::ToS3Request`] for request conversion and [`s3::types::S3Api`] for execution //! - Builders implement [`s3::types::ToS3Request`] for request conversion and [`s3::types::S3Api`] for execution
//! - Responses implement [`s3::types::FromS3Response`] for consistent deserialization //! - Responses implement [`s3::types::FromS3Response`] for consistent deserialization

View File

@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
//! Argument builders for [minio::s3::client::Client](crate::s3::client::Client) APIs //! Argument builders for [minio::s3::client::Client](crate::s3::client::MinioClient) APIs
mod append_object; mod append_object;
mod bucket_common; mod bucket_common;

View File

@ -13,10 +13,10 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::Client;
use crate::s3::builders::{ use crate::s3::builders::{
ContentStream, MAX_MULTIPART_COUNT, ObjectContent, Size, calc_part_info, ContentStream, MAX_MULTIPART_COUNT, ObjectContent, Size, calc_part_info,
}; };
use crate::s3::client::MinioClient;
use crate::s3::error::ValidationErr; use crate::s3::error::ValidationErr;
use crate::s3::error::{Error, IoError}; use crate::s3::error::{Error, IoError};
use crate::s3::header_constants::*; use crate::s3::header_constants::*;
@ -29,61 +29,62 @@ use crate::s3::types::{S3Api, S3Request, ToS3Request};
use crate::s3::utils::{check_bucket_name, check_object_name, check_sse}; use crate::s3::utils::{check_bucket_name, check_object_name, check_sse};
use http::Method; use http::Method;
use std::sync::Arc; use std::sync::Arc;
use typed_builder::TypedBuilder;
// region: append-object // region: append-object
/// Argument builder for the [`AppendObject`](https://docs.aws.amazon.com/AmazonS3/latest/userguide/directory-buckets-objects-append.html) S3 API operation. /// Argument builder for the [`AppendObject`](https://docs.aws.amazon.com/AmazonS3/latest/userguide/directory-buckets-objects-append.html) S3 API operation.
/// ///
/// This struct constructs the parameters required for the [`Client::append_object`](crate::s3::client::Client::append_object) method. /// This struct constructs the parameters required for the [`Client::append_object`](crate::s3::client::MinioClient::append_object) method.
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, TypedBuilder)]
pub struct AppendObject { pub struct AppendObject {
client: Client, #[builder(!default)] // force required
client: MinioClient,
#[builder(default, setter(into))]
extra_headers: Option<Multimap>, extra_headers: Option<Multimap>,
#[builder(default, setter(into))]
extra_query_params: Option<Multimap>, extra_query_params: Option<Multimap>,
#[builder(setter(into))] // force required + accept Into<String>
bucket: String, bucket: String,
#[builder(setter(into))] // force required + accept Into<String>
object: String, object: String,
#[builder(default, setter(into))]
region: Option<String>, region: Option<String>,
sse: Option<Arc<dyn Sse>>,
data: SegmentedBytes,
#[builder(default, setter(into))]
sse: Option<Arc<dyn Sse>>,
#[builder(!default)] // force required
data: Arc<SegmentedBytes>,
#[builder(!default)] // force required
/// value of x-amz-write-offset-bytes /// value of x-amz-write-offset-bytes
offset_bytes: u64, offset_bytes: u64,
} }
impl AppendObject {
pub fn new(
client: Client,
bucket: String,
object: String,
data: SegmentedBytes,
offset_bytes: u64,
) -> Self {
Self {
client,
bucket,
object,
offset_bytes,
data,
..Default::default()
}
}
pub fn extra_headers(mut self, extra_headers: Option<Multimap>) -> Self {
self.extra_headers = extra_headers;
self
}
pub fn extra_query_params(mut self, extra_query_params: Option<Multimap>) -> Self {
self.extra_query_params = extra_query_params;
self
}
}
impl S3Api for AppendObject { impl S3Api for AppendObject {
type S3Response = AppendObjectResponse; type S3Response = AppendObjectResponse;
} }
/// Builder type for [`AppendObject`] that is returned by [`MinioClient::append_object`](crate::s3::client::MinioClient::append_object).
///
/// This type alias simplifies the complex generic signature generated by the `typed_builder` crate.
pub type AppendObjectBldr = AppendObjectBuilder<(
(MinioClient,),
(),
(),
(String,),
(String,),
(),
(),
(Arc<SegmentedBytes>,),
(u64,),
)>;
impl ToS3Request for AppendObject { impl ToS3Request for AppendObject {
fn to_s3request(self) -> Result<S3Request, ValidationErr> { fn to_s3request(self) -> Result<S3Request, ValidationErr> {
check_bucket_name(&self.bucket, true)?; check_bucket_name(&self.bucket, true)?;
@ -93,13 +94,16 @@ impl ToS3Request for AppendObject {
let mut headers: Multimap = self.extra_headers.unwrap_or_default(); let mut headers: Multimap = self.extra_headers.unwrap_or_default();
headers.add(X_AMZ_WRITE_OFFSET_BYTES, self.offset_bytes.to_string()); headers.add(X_AMZ_WRITE_OFFSET_BYTES, self.offset_bytes.to_string());
Ok(S3Request::new(self.client, Method::PUT) Ok(S3Request::builder()
.client(self.client)
.method(Method::PUT)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.query_params(self.extra_query_params.unwrap_or_default()) .query_params(self.extra_query_params.unwrap_or_default())
.object(Some(self.object)) .object(self.object)
.headers(headers) .headers(headers)
.body(Some(self.data))) .body(self.data)
.build())
} }
} }
// endregion: append-object // endregion: append-object
@ -108,83 +112,59 @@ impl ToS3Request for AppendObject {
/// Argument builder for the [`AppendObject`](https://docs.aws.amazon.com/AmazonS3/latest/userguide/directory-buckets-objects-append.html) S3 API operation. /// Argument builder for the [`AppendObject`](https://docs.aws.amazon.com/AmazonS3/latest/userguide/directory-buckets-objects-append.html) S3 API operation.
/// ///
/// This struct constructs the parameters required for the [`Client::append_object_content`](crate::s3::client::Client::append_object_content) method. /// This struct constructs the parameters required for the [`Client::append_object_content`](crate::s3::client::MinioClient::append_object_content) method.
/// It is High-level API for appending content to an object using multipart uploads. /// It is High-level API for appending content to an object using multipart uploads.
/// ///
/// `AppendObjectContent` consumes an [`ObjectContent`] stream and transparently appends it to an existing object in MinIO or S3, /// `AppendObjectContent` consumes an [`ObjectContent`] stream and transparently appends it to an existing object in MinIO or S3,
/// managing multipart upload details internally. /// managing multipart upload details internally.
#[derive(Default)] #[derive(TypedBuilder)]
pub struct AppendObjectContent { pub struct AppendObjectContent {
client: Client, #[builder(!default)] // force required
client: MinioClient,
#[builder(default, setter(into))]
extra_headers: Option<Multimap>, extra_headers: Option<Multimap>,
#[builder(default, setter(into))]
extra_query_params: Option<Multimap>, extra_query_params: Option<Multimap>,
#[builder(default, setter(into))]
region: Option<String>, region: Option<String>,
#[builder(setter(into))] // force required + accept Into<String>
bucket: String, bucket: String,
#[builder(setter(into))] // force required + accept Into<String>
object: String, object: String,
#[builder(default)]
sse: Option<Arc<dyn Sse>>, sse: Option<Arc<dyn Sse>>,
#[builder(default = Size::Unknown)]
part_size: Size, part_size: Size,
#[builder(!default, setter(into))]
// source data
input_content: ObjectContent, input_content: ObjectContent,
#[builder(default = ContentStream::empty())]
// Computed.
content_stream: ContentStream, content_stream: ContentStream,
#[builder(default)]
part_count: Option<u16>, part_count: Option<u16>,
/// Value of x-amz-write-offset-bytes /// Value of x-amz-write-offset-bytes
#[builder(default)]
offset_bytes: u64, offset_bytes: u64,
} }
/// Builder type for [`AppendObjectContent`] that is returned by [`MinioClient::append_object_content`](crate::s3::client::MinioClient::append_object_content).
///
/// This type alias simplifies the complex generic signature generated by the `typed_builder` crate.
pub type AppendObjectContentBldr = AppendObjectContentBuilder<(
(MinioClient,),
(),
(),
(),
(String,),
(String,),
(),
(),
(ObjectContent,),
(),
(),
(),
)>;
impl AppendObjectContent { impl AppendObjectContent {
pub fn new(
client: Client,
bucket: String,
object: String,
content: impl Into<ObjectContent>,
) -> Self {
Self {
client,
bucket,
object,
input_content: content.into(),
extra_headers: None,
extra_query_params: None,
region: None,
sse: None,
part_size: Size::Unknown,
content_stream: ContentStream::empty(),
part_count: None,
offset_bytes: 0,
}
}
pub fn extra_headers(mut self, extra_headers: Option<Multimap>) -> Self {
self.extra_headers = extra_headers;
self
}
pub fn extra_query_params(mut self, extra_query_params: Option<Multimap>) -> Self {
self.extra_query_params = extra_query_params;
self
}
/// Sets the region for the request
pub fn region(mut self, region: Option<String>) -> Self {
self.region = region;
self
}
pub fn part_size(mut self, part_size: impl Into<Size>) -> Self {
self.part_size = part_size.into();
self
}
pub fn offset_bytes(mut self, offset_bytes: u64) -> Self {
self.offset_bytes = offset_bytes;
self
}
pub async fn send(mut self) -> Result<AppendObjectResponse, Error> { pub async fn send(mut self) -> Result<AppendObjectResponse, Error> {
check_bucket_name(&self.bucket, true)?; check_bucket_name(&self.bucket, true)?;
check_object_name(&self.object)?; check_object_name(&self.object)?;
@ -223,6 +203,7 @@ impl AppendObjectContent {
let resp: StatObjectResponse = self let resp: StatObjectResponse = self
.client .client
.stat_object(&self.bucket, &self.object) .stat_object(&self.bucket, &self.object)
.build()
.send() .send()
.await?; .await?;
//println!("statObjectResponse={:#?}", resp); //println!("statObjectResponse={:#?}", resp);
@ -247,12 +228,13 @@ impl AppendObjectContent {
region: self.region, region: self.region,
offset_bytes: current_file_size, offset_bytes: current_file_size,
sse: self.sse, sse: self.sse,
data: seg_bytes, data: Arc::new(seg_bytes),
}; };
ao.send().await ao.send().await
} else if object_size.is_known() && (seg_bytes.len() as u64) < part_size { } else if let Some(expected) = object_size.value()
&& (seg_bytes.len() as u64) < part_size
{
// Not enough data! // Not enough data!
let expected = object_size.as_u64().unwrap();
let got = seg_bytes.len() as u64; let got = seg_bytes.len() as u64;
Err(ValidationErr::InsufficientData { expected, got })? Err(ValidationErr::InsufficientData { expected, got })?
} else { } else {
@ -312,7 +294,7 @@ impl AppendObjectContent {
object: self.object.clone(), object: self.object.clone(),
region: self.region.clone(), region: self.region.clone(),
sse: self.sse.clone(), sse: self.sse.clone(),
data: part_content, data: Arc::new(part_content),
offset_bytes: next_offset_bytes, offset_bytes: next_offset_bytes,
}; };
let resp: AppendObjectResponse = append_object.send().await?; let resp: AppendObjectResponse = append_object.send().await?;

View File

@ -13,49 +13,26 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::client::Client; use crate::s3::client::MinioClient;
use crate::s3::multimap_ext::Multimap; use crate::s3::multimap_ext::Multimap;
use std::marker::PhantomData; use std::marker::PhantomData;
use typed_builder::TypedBuilder;
/// Common parameters for bucket operations /// Common parameters for bucket operations
/// #[derive(Clone, Debug, TypedBuilder)]
/// See [Amazon S3 Buckets](https://docs.aws.amazon.com/AmazonS3/latest/userguide/UsingBucket.html) for more information. pub struct BucketCommon<T> {
#[derive(Clone, Debug, Default)] #[builder(!default)] // force required
pub struct BucketCommon<A> { pub(crate) client: MinioClient,
pub(crate) client: Client,
#[builder(default, setter(into))]
pub(crate) extra_headers: Option<Multimap>, pub(crate) extra_headers: Option<Multimap>,
#[builder(default, setter(into))]
pub(crate) extra_query_params: Option<Multimap>, pub(crate) extra_query_params: Option<Multimap>,
#[builder(default, setter(into))]
pub(crate) region: Option<String>, pub(crate) region: Option<String>,
#[builder(setter(into))] // force required + accept Into<String>
pub(crate) bucket: String, pub(crate) bucket: String,
_operation: PhantomData<A>, #[builder(default)]
} _operation: PhantomData<T>,
impl<A: Default> BucketCommon<A> {
pub fn new(client: Client, bucket: String) -> BucketCommon<A> {
BucketCommon {
client,
bucket,
..Default::default()
}
}
/// Sets extra headers for the request
pub fn extra_headers(mut self, extra_headers: Option<Multimap>) -> Self {
self.extra_headers = extra_headers;
self
}
/// Sets extra query parameters for the request
pub fn extra_query_params(mut self, extra_query_params: Option<Multimap>) -> Self {
self.extra_query_params = extra_query_params;
self
}
/// Sets the region for the request
pub fn region(mut self, region: Option<String>) -> Self {
self.region = region;
self
}
} }

View File

@ -13,35 +13,45 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::builders::BucketCommon; use crate::s3::MinioClient;
use crate::s3::builders::{BucketCommon, BucketCommonBuilder};
use crate::s3::error::ValidationErr; use crate::s3::error::ValidationErr;
use crate::s3::response::BucketExistsResponse; use crate::s3::response::BucketExistsResponse;
use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::types::{S3Api, S3Request, ToS3Request};
use crate::s3::utils::check_bucket_name; use crate::s3::utils::check_bucket_name;
use http::Method; use http::Method;
/// This struct constructs the parameters required for the [`Client::bucket_exists`](crate::s3::client::Client::bucket_exists) method. /// This struct constructs the parameters required for the [`Client::bucket_exists`](crate::s3::client::MinioClient::bucket_exists) method.
/// ///
/// See [Amazon S3: Working with Buckets](https://docs.aws.amazon.com/AmazonS3/latest/userguide/UsingBucket.html) /// See [Amazon S3: Working with Buckets](https://docs.aws.amazon.com/AmazonS3/latest/userguide/UsingBucket.html)
/// for more information about checking if a bucket exists. /// for more information about checking if a bucket exists.
pub type BucketExists = BucketCommon<BucketExistsPhantomData>; pub type BucketExists = BucketCommon<BucketExistsPhantomData>;
#[doc(hidden)] #[doc(hidden)]
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug)]
pub struct BucketExistsPhantomData; pub struct BucketExistsPhantomData;
impl S3Api for BucketExists { impl S3Api for BucketExists {
type S3Response = BucketExistsResponse; type S3Response = BucketExistsResponse;
} }
/// Builder type for [`BucketExists`] that is returned by [`MinioClient::bucket_exists`](crate::s3::client::MinioClient::bucket_exists).
///
/// This type alias simplifies the complex generic signature generated by the `typed_builder` crate.
pub type BucketExistsBldr =
BucketCommonBuilder<BucketExistsPhantomData, ((MinioClient,), (), (), (), (String,), ())>;
impl ToS3Request for BucketExists { impl ToS3Request for BucketExists {
fn to_s3request(self) -> Result<S3Request, ValidationErr> { fn to_s3request(self) -> Result<S3Request, ValidationErr> {
check_bucket_name(&self.bucket, true)?; check_bucket_name(&self.bucket, true)?;
Ok(S3Request::new(self.client, Method::HEAD) Ok(S3Request::builder()
.client(self.client)
.method(Method::HEAD)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.query_params(self.extra_query_params.unwrap_or_default()) .query_params(self.extra_query_params.unwrap_or_default())
.headers(self.extra_headers.unwrap_or_default())) .headers(self.extra_headers.unwrap_or_default())
.build())
} }
} }

View File

@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::Client; use crate::s3::client::MinioClient;
use crate::s3::client::{MAX_MULTIPART_COUNT, MAX_PART_SIZE}; use crate::s3::client::{MAX_MULTIPART_COUNT, MAX_PART_SIZE};
use crate::s3::error::{Error, ValidationErr}; use crate::s3::error::{Error, ValidationErr};
use crate::s3::header_constants::*; use crate::s3::header_constants::*;
@ -34,67 +34,52 @@ use async_recursion::async_recursion;
use http::Method; use http::Method;
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::Arc; use std::sync::Arc;
use typed_builder::TypedBuilder;
/// Argument builder for the [`UploadPartCopy`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html) S3 API operation. /// Argument builder for the [`UploadPartCopy`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html) S3 API operation.
/// ///
/// This struct constructs the parameters required for the [`Client::upload_part_copy`](crate::s3::client::Client::upload_part_copy) method. /// This struct constructs the parameters required for the [`Client::upload_part_copy`](crate::s3::client::MinioClient::upload_part_copy) method.
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, TypedBuilder)]
pub struct UploadPartCopy { pub struct UploadPartCopy {
client: Client, #[builder(!default)] // force required
client: MinioClient,
#[builder(default, setter(into))]
extra_headers: Option<Multimap>, extra_headers: Option<Multimap>,
#[builder(default, setter(into))]
extra_query_params: Option<Multimap>, extra_query_params: Option<Multimap>,
#[builder(default, setter(into))]
region: Option<String>, region: Option<String>,
#[builder(setter(into))] // force required + accept Into<String>
bucket: String, bucket: String,
#[builder(setter(into))] // force required + accept Into<String>
object: String, object: String,
#[builder(setter(into))] // force required + accept Into<String>
upload_id: String, upload_id: String,
#[builder(default = 0)]
part_number: u16, part_number: u16,
#[builder(default)]
headers: Multimap, headers: Multimap,
} }
impl UploadPartCopy {
pub fn new(client: Client, bucket: String, object: String, upload_id: String) -> Self {
Self {
client,
bucket,
object,
upload_id,
..Default::default()
}
}
pub fn extra_headers(mut self, extra_headers: Option<Multimap>) -> Self {
self.extra_headers = extra_headers;
self
}
pub fn extra_query_params(mut self, extra_query_params: Option<Multimap>) -> Self {
self.extra_query_params = extra_query_params;
self
}
/// Sets the region for the request
pub fn region(mut self, region: Option<String>) -> Self {
self.region = region;
self
}
pub fn part_number(mut self, part_number: u16) -> Self {
self.part_number = part_number;
self
}
pub fn headers(mut self, headers: Multimap) -> Self {
self.headers = headers;
self
}
}
impl S3Api for UploadPartCopy { impl S3Api for UploadPartCopy {
type S3Response = UploadPartCopyResponse; type S3Response = UploadPartCopyResponse;
} }
/// Builder type for [`UploadPartCopy`] that is returned by [`MinioClient::upload_part_copy`](crate::s3::client::MinioClient::upload_part_copy).
///
/// This type alias simplifies the complex generic signature generated by the `typed_builder` crate.
pub type UploadPartCopyBldr = UploadPartCopyBuilder<(
(MinioClient,),
(),
(),
(),
(String,),
(String,),
(String,),
(),
(),
)>;
impl ToS3Request for UploadPartCopy { impl ToS3Request for UploadPartCopy {
fn to_s3request(self) -> Result<S3Request, ValidationErr> { fn to_s3request(self) -> Result<S3Request, ValidationErr> {
{ {
@ -121,113 +106,77 @@ impl ToS3Request for UploadPartCopy {
query_params.add("uploadId", self.upload_id); query_params.add("uploadId", self.upload_id);
} }
Ok(S3Request::new(self.client, Method::PUT) Ok(S3Request::builder()
.client(self.client)
.method(Method::PUT)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.object(Some(self.object)) .object(self.object)
.query_params(query_params) .query_params(query_params)
.headers(headers)) .headers(headers)
.build())
} }
} }
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, TypedBuilder)]
pub struct CopyObjectInternal { pub struct CopyObjectInternal {
client: Client, #[builder(!default)] // force required
client: MinioClient,
#[builder(default, setter(into))]
extra_headers: Option<Multimap>, extra_headers: Option<Multimap>,
#[builder(default, setter(into))]
extra_query_params: Option<Multimap>, extra_query_params: Option<Multimap>,
region: Option<String>, #[builder(default, setter(into))]
pub(crate) region: Option<String>,
#[builder(setter(into))] // force required + accept Into<String>
bucket: String, bucket: String,
#[builder(setter(into))] // force required + accept Into<String>
object: String, object: String,
#[builder(default)]
headers: Multimap, headers: Multimap,
#[builder(default, setter(into))]
user_metadata: Option<Multimap>, user_metadata: Option<Multimap>,
#[builder(default, setter(into))]
sse: Option<Arc<dyn Sse>>, sse: Option<Arc<dyn Sse>>,
#[builder(default, setter(into))]
tags: Option<HashMap<String, String>>, tags: Option<HashMap<String, String>>,
#[builder(default, setter(into))]
retention: Option<Retention>, retention: Option<Retention>,
#[builder(default)]
legal_hold: bool, legal_hold: bool,
#[builder(!default)] // force required
source: CopySource, source: CopySource,
#[builder(default, setter(into))]
metadata_directive: Option<Directive>, metadata_directive: Option<Directive>,
#[builder(default, setter(into))]
tagging_directive: Option<Directive>, tagging_directive: Option<Directive>,
} }
impl CopyObjectInternal {
pub fn new(client: Client, bucket: String, object: String) -> Self {
Self {
client,
bucket,
object,
..Default::default()
}
}
pub fn extra_headers(mut self, extra_headers: Option<Multimap>) -> Self {
self.extra_headers = extra_headers;
self
}
pub fn extra_query_params(mut self, extra_query_params: Option<Multimap>) -> Self {
self.extra_query_params = extra_query_params;
self
}
/// Sets the region for the request
pub fn region(mut self, region: Option<String>) -> Self {
self.region = region;
self
}
pub fn headers(mut self, headers: Multimap) -> Self {
self.headers = headers;
self
}
pub fn user_metadata(mut self, user_metadata: Option<Multimap>) -> Self {
self.user_metadata = user_metadata;
self
}
pub fn sse(mut self, sse: Option<Arc<dyn Sse>>) -> Self {
self.sse = sse;
self
}
pub fn tags(mut self, tags: Option<HashMap<String, String>>) -> Self {
self.tags = tags;
self
}
pub fn retention(mut self, retention: Option<Retention>) -> Self {
self.retention = retention;
self
}
pub fn legal_hold(mut self, legal_hold: bool) -> Self {
self.legal_hold = legal_hold;
self
}
pub fn source(mut self, source: CopySource) -> Self {
self.source = source;
self
}
pub fn metadata_directive(mut self, metadata_directive: Option<Directive>) -> Self {
self.metadata_directive = metadata_directive;
self
}
pub fn tagging_directive(mut self, tagging_directive: Option<Directive>) -> Self {
self.tagging_directive = tagging_directive;
self
}
}
impl S3Api for CopyObjectInternal { impl S3Api for CopyObjectInternal {
type S3Response = CopyObjectInternalResponse; type S3Response = CopyObjectInternalResponse;
} }
/// Builder type for [`CopyObjectInternal`] that is returned by [`MinioClient::copy_object_internal`](crate::s3::client::MinioClient::copy_object_internal).
///
/// This type alias simplifies the complex generic signature generated by the `typed_builder` crate.
pub type CopyObjectInternalBldr = CopyObjectInternalBuilder<(
(MinioClient,),
(),
(),
(),
(String,),
(String,),
(),
(),
(),
(),
(),
(),
(),
(),
(),
)>;
impl ToS3Request for CopyObjectInternal { impl ToS3Request for CopyObjectInternal {
fn to_s3request(self) -> Result<S3Request, ValidationErr> { fn to_s3request(self) -> Result<S3Request, ValidationErr> {
check_sse(&self.sse, &self.client)?; check_sse(&self.sse, &self.client)?;
@ -314,105 +263,77 @@ impl ToS3Request for CopyObjectInternal {
} }
}; };
Ok(S3Request::new(self.client, Method::PUT) Ok(S3Request::builder()
.client(self.client)
.method(Method::PUT)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.object(Some(self.object)) .object(self.object)
.query_params(self.extra_query_params.unwrap_or_default()) .query_params(self.extra_query_params.unwrap_or_default())
.headers(headers)) .headers(headers)
.build())
} }
} }
/// Argument builder for [`CopyObject`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html) S3 API operation. /// Argument builder for [`CopyObject`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html) S3 API operation.
/// ///
/// This struct constructs the parameters required for the [`Client::copy_object`](crate::s3::client::Client::copy_object) method. /// This struct constructs the parameters required for the [`Client::copy_object`](crate::s3::client::MinioClient::copy_object) method.
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, TypedBuilder)]
pub struct CopyObject { pub struct CopyObject {
client: Client, #[builder(!default)] // force required
client: MinioClient,
#[builder(default, setter(into))]
extra_headers: Option<Multimap>, extra_headers: Option<Multimap>,
#[builder(default, setter(into))]
extra_query_params: Option<Multimap>, extra_query_params: Option<Multimap>,
region: Option<String>, #[builder(default, setter(into))]
pub(crate) region: Option<String>,
#[builder(setter(into))] // force required + accept Into<String>
bucket: String, bucket: String,
#[builder(setter(into))] // force required + accept Into<String>
object: String, object: String,
#[builder(default, setter(into))]
headers: Option<Multimap>, headers: Option<Multimap>,
#[builder(default, setter(into))]
user_metadata: Option<Multimap>, user_metadata: Option<Multimap>,
#[builder(default, setter(into))]
sse: Option<Arc<dyn Sse>>, sse: Option<Arc<dyn Sse>>,
#[builder(default, setter(into))]
tags: Option<HashMap<String, String>>, tags: Option<HashMap<String, String>>,
#[builder(default, setter(into))]
retention: Option<Retention>, retention: Option<Retention>,
#[builder(default = false)]
legal_hold: bool, legal_hold: bool,
#[builder(!default)] // force required
source: CopySource, source: CopySource,
#[builder(default, setter(into))]
metadata_directive: Option<Directive>, metadata_directive: Option<Directive>,
#[builder(default, setter(into))]
tagging_directive: Option<Directive>, tagging_directive: Option<Directive>,
} }
/// Builder type for [`CopyObject`] that is returned by [`MinioClient::copy_object`](crate::s3::client::MinioClient::copy_object).
///
/// This type alias simplifies the complex generic signature generated by the `typed_builder` crate.
pub type CopyObjectBldr = CopyObjectBuilder<(
(MinioClient,),
(),
(),
(),
(String,),
(String,),
(),
(),
(),
(),
(),
(),
(),
(),
(),
)>;
impl CopyObject { impl CopyObject {
pub fn new(client: Client, bucket: String, object: String) -> Self {
Self {
client,
bucket,
object,
..Default::default()
}
}
pub fn extra_headers(mut self, extra_headers: Option<Multimap>) -> Self {
self.extra_headers = extra_headers;
self
}
pub fn extra_query_params(mut self, extra_query_params: Option<Multimap>) -> Self {
self.extra_query_params = extra_query_params;
self
}
/// Sets the region for the request
pub fn region(mut self, region: Option<String>) -> Self {
self.region = region;
self
}
pub fn headers(mut self, headers: Option<Multimap>) -> Self {
self.headers = headers;
self
}
pub fn user_metadata(mut self, user_metadata: Option<Multimap>) -> Self {
self.user_metadata = user_metadata;
self
}
pub fn sse(mut self, sse: Option<Arc<dyn Sse>>) -> Self {
self.sse = sse;
self
}
pub fn tags(mut self, tags: Option<HashMap<String, String>>) -> Self {
self.tags = tags;
self
}
pub fn retention(mut self, retention: Option<Retention>) -> Self {
self.retention = retention;
self
}
pub fn legal_hold(mut self, legal_hold: bool) -> Self {
self.legal_hold = legal_hold;
self
}
/// Sets the source for the copy operation.
pub fn source(mut self, source: CopySource) -> Self {
self.source = source;
self
}
pub fn metadata_directive(mut self, metadata_directive: Option<Directive>) -> Self {
self.metadata_directive = metadata_directive;
self
}
pub fn tagging_directive(mut self, tagging_directive: Option<Directive>) -> Self {
self.tagging_directive = tagging_directive;
self
}
/// Sends the copy object request. /// Sends the copy object request.
/// ///
/// Functionally related to the [S3Api::send()](crate::s3::types::S3Api::send) method, but /// Functionally related to the [S3Api::send()](crate::s3::types::S3Api::send) method, but
@ -434,6 +355,7 @@ impl CopyObject {
.not_match_etag(source.not_match_etag) .not_match_etag(source.not_match_etag)
.modified_since(source.modified_since) .modified_since(source.modified_since)
.unmodified_since(source.unmodified_since) .unmodified_since(source.unmodified_since)
.build()
.send() .send()
.await?; .await?;
@ -490,6 +412,7 @@ impl CopyObject {
.tags(self.tags) .tags(self.tags)
.retention(self.retention) .retention(self.retention)
.legal_hold(self.legal_hold) .legal_hold(self.legal_hold)
.build()
.send() .send()
.await?; .await?;
@ -511,6 +434,7 @@ impl CopyObject {
.source(self.source) .source(self.source)
.metadata_directive(self.metadata_directive) .metadata_directive(self.metadata_directive)
.tagging_directive(self.tagging_directive) .tagging_directive(self.tagging_directive)
.build()
.send() .send()
.await?; .await?;
@ -520,86 +444,56 @@ impl CopyObject {
} }
} }
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, TypedBuilder)]
pub struct ComposeObjectInternal { pub struct ComposeObjectInternal {
client: Client, #[builder(!default)] // force required
client: MinioClient,
#[builder(default, setter(into))]
extra_headers: Option<Multimap>, extra_headers: Option<Multimap>,
#[builder(default, setter(into))]
extra_query_params: Option<Multimap>, extra_query_params: Option<Multimap>,
region: Option<String>, #[builder(default, setter(into))]
pub(crate) region: Option<String>,
#[builder(setter(into))] // force required + accept Into<String>
bucket: String, bucket: String,
#[builder(setter(into))] // force required + accept Into<String>
object: String, object: String,
#[builder(default, setter(into))]
headers: Option<Multimap>, headers: Option<Multimap>,
#[builder(default, setter(into))]
user_metadata: Option<Multimap>, user_metadata: Option<Multimap>,
#[builder(default, setter(into))]
sse: Option<Arc<dyn Sse>>, sse: Option<Arc<dyn Sse>>,
#[builder(default, setter(into))]
tags: Option<HashMap<String, String>>, tags: Option<HashMap<String, String>>,
#[builder(default, setter(into))]
retention: Option<Retention>, retention: Option<Retention>,
#[builder(default)]
legal_hold: bool, legal_hold: bool,
#[builder(default)]
sources: Vec<ComposeSource>, sources: Vec<ComposeSource>,
} }
/// Builder type for [`ComposeObjectInternal`] that is returned by [`MinioClient::compose_object_internal`](crate::s3::client::MinioClient::compose_object_internal).
///
/// This type alias simplifies the complex generic signature generated by the `typed_builder` crate.
pub type ComposeObjectInternalBldr = ComposeObjectInternalBuilder<(
(MinioClient,),
(),
(),
(),
(String,),
(String,),
(),
(),
(),
(),
(),
(),
(),
)>;
impl ComposeObjectInternal { impl ComposeObjectInternal {
pub fn new(client: Client, bucket: String, object: String) -> Self {
Self {
client,
bucket,
object,
..Default::default()
}
}
pub fn extra_headers(mut self, extra_headers: Option<Multimap>) -> Self {
self.extra_headers = extra_headers;
self
}
pub fn extra_query_params(mut self, extra_query_params: Option<Multimap>) -> Self {
self.extra_query_params = extra_query_params;
self
}
/// Sets the region for the request
pub fn region(mut self, region: Option<String>) -> Self {
self.region = region;
self
}
pub fn headers(mut self, headers: Option<Multimap>) -> Self {
self.headers = headers;
self
}
pub fn user_metadata(mut self, user_metadata: Option<Multimap>) -> Self {
self.user_metadata = user_metadata;
self
}
pub fn sse(mut self, sse: Option<Arc<dyn Sse>>) -> Self {
self.sse = sse;
self
}
pub fn tags(mut self, tags: Option<HashMap<String, String>>) -> Self {
self.tags = tags;
self
}
pub fn retention(mut self, retention: Option<Retention>) -> Self {
self.retention = retention;
self
}
pub fn legal_hold(mut self, legal_hold: bool) -> Self {
self.legal_hold = legal_hold;
self
}
pub fn sources(mut self, sources: Vec<ComposeSource>) -> Self {
self.sources = sources;
self
}
#[async_recursion] #[async_recursion]
pub async fn send(self) -> (Result<ComposeObjectResponse, Error>, String) { pub async fn send(self) -> (Result<ComposeObjectResponse, Error>, String) {
let mut upload_id = String::new(); let mut upload_id = String::new();
@ -627,6 +521,13 @@ impl ComposeObjectInternal {
.tags(self.tags) .tags(self.tags)
.retention(self.retention) .retention(self.retention)
.legal_hold(self.legal_hold) .legal_hold(self.legal_hold)
.source(
CopySource::builder()
.bucket(&self.bucket)
.object(&self.object)
.build(),
) // TODO redundant use of bucket and object
.build()
.send() .send()
.await .await
{ {
@ -653,6 +554,7 @@ impl ComposeObjectInternal {
.extra_query_params(self.extra_query_params.clone()) .extra_query_params(self.extra_query_params.clone())
.region(self.region.clone()) .region(self.region.clone())
.extra_headers(Some(headers)) .extra_headers(Some(headers))
.build()
.send() .send()
.await .await
{ {
@ -710,6 +612,7 @@ impl ComposeObjectInternal {
.region(self.region.clone()) .region(self.region.clone())
.part_number(part_number) .part_number(part_number)
.headers(headers) .headers(headers)
.build()
.send() .send()
.await .await
{ {
@ -749,6 +652,7 @@ impl ComposeObjectInternal {
.region(self.region.clone()) .region(self.region.clone())
.part_number(part_number) .part_number(part_number)
.headers(headers_copy) .headers(headers_copy)
.build()
.send() .send()
.await .await
{ {
@ -777,6 +681,7 @@ impl ComposeObjectInternal {
.client .client
.complete_multipart_upload(&self.bucket, &self.object, &upload_id, parts) .complete_multipart_upload(&self.bucket, &self.object, &upload_id, parts)
.region(self.region) .region(self.region)
.build()
.send() .send()
.await; .await;
@ -798,87 +703,57 @@ impl ComposeObjectInternal {
/// Argument builder for [`CopyObject`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html) S3 API operation. /// Argument builder for [`CopyObject`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html) S3 API operation.
/// ///
/// See [Amazon S3 Multipart Upload](https://docs.aws.amazon.com/AmazonS3/latest/userguide/mpuoverview.html) /// See [Amazon S3 Multipart Upload](https://docs.aws.amazon.com/AmazonS3/latest/userguide/mpuoverview.html)
/// This struct constructs the parameters required for the [`Client::copy_object`](crate::s3::client::Client::copy_object) method. /// This struct constructs the parameters required for the [`Client::copy_object`](crate::s3::client::MinioClient::copy_object) method.
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, TypedBuilder)]
pub struct ComposeObject { pub struct ComposeObject {
client: Client, #[builder(!default)] // force required
client: MinioClient,
#[builder(default)]
extra_headers: Option<Multimap>, extra_headers: Option<Multimap>,
#[builder(default, setter(into))]
extra_query_params: Option<Multimap>, extra_query_params: Option<Multimap>,
#[builder(default, setter(into))]
region: Option<String>, region: Option<String>,
#[builder(setter(into))] // force required + accept Into<String>
bucket: String, bucket: String,
#[builder(setter(into))] // force required + accept Into<String>
object: String, object: String,
#[builder(default, setter(into))]
headers: Option<Multimap>, headers: Option<Multimap>,
#[builder(default, setter(into))]
user_metadata: Option<Multimap>, user_metadata: Option<Multimap>,
#[builder(default, setter(into))]
sse: Option<Arc<dyn Sse>>, sse: Option<Arc<dyn Sse>>,
#[builder(default, setter(into))]
tags: Option<HashMap<String, String>>, tags: Option<HashMap<String, String>>,
#[builder(default, setter(into))]
retention: Option<Retention>, retention: Option<Retention>,
#[builder(default)]
legal_hold: bool, legal_hold: bool,
#[builder(default)]
sources: Vec<ComposeSource>, sources: Vec<ComposeSource>,
} }
/// Builder type for [`ComposeObject`] that is returned by [`MinioClient::compose_object`](crate::s3::client::MinioClient::compose_object).
///
/// This type alias simplifies the complex generic signature generated by the `typed_builder` crate.
pub type ComposeObjectBldr = ComposeObjectBuilder<(
(MinioClient,),
(),
(),
(),
(String,),
(String,),
(),
(),
(),
(),
(),
(),
(Vec<ComposeSource>,),
)>;
impl ComposeObject { impl ComposeObject {
pub fn new(client: Client, bucket: String, object: String) -> Self {
Self {
client,
bucket,
object,
..Default::default()
}
}
pub fn extra_headers(mut self, extra_headers: Option<Multimap>) -> Self {
self.extra_headers = extra_headers;
self
}
pub fn extra_query_params(mut self, extra_query_params: Option<Multimap>) -> Self {
self.extra_query_params = extra_query_params;
self
}
/// Sets the region for the request
pub fn region(mut self, region: Option<String>) -> Self {
self.region = region;
self
}
pub fn headers(mut self, headers: Option<Multimap>) -> Self {
self.headers = headers;
self
}
pub fn user_metadata(mut self, user_metadata: Option<Multimap>) -> Self {
self.user_metadata = user_metadata;
self
}
pub fn sse(mut self, sse: Option<Arc<dyn Sse>>) -> Self {
self.sse = sse;
self
}
pub fn tags(mut self, tags: Option<HashMap<String, String>>) -> Self {
self.tags = tags;
self
}
pub fn retention(mut self, retention: Option<Retention>) -> Self {
self.retention = retention;
self
}
pub fn legal_hold(mut self, legal_hold: bool) -> Self {
self.legal_hold = legal_hold;
self
}
pub fn sources(mut self, sources: Vec<ComposeSource>) -> Self {
self.sources = sources;
self
}
pub async fn send(self) -> Result<ComposeObjectResponse, Error> { pub async fn send(self) -> Result<ComposeObjectResponse, Error> {
check_sse(&self.sse, &self.client)?; check_sse(&self.sse, &self.client)?;
@ -898,6 +773,7 @@ impl ComposeObject {
.retention(self.retention) .retention(self.retention)
.legal_hold(self.legal_hold) .legal_hold(self.legal_hold)
.sources(self.sources) .sources(self.sources)
.build()
.send() .send()
.await; .await;
@ -908,6 +784,7 @@ impl ComposeObject {
let _resp: AbortMultipartUploadResponse = self let _resp: AbortMultipartUploadResponse = self
.client .client
.abort_multipart_upload(&bucket, &object, &upload_id) .abort_multipart_upload(&bucket, &object, &upload_id)
.build()
.send() .send()
.await?; .await?;
} }
@ -920,7 +797,7 @@ impl ComposeObject {
// region: misc // region: misc
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, Default)]
/// Source object information for [compose_object](Client::compose_object) /// Source object information for [compose_object](MinioClient::compose_object)
pub struct ComposeSource { pub struct ComposeSource {
pub extra_headers: Option<Multimap>, pub extra_headers: Option<Multimap>,
pub extra_query_params: Option<Multimap>, pub extra_query_params: Option<Multimap>,
@ -1050,36 +927,38 @@ impl ComposeSource {
} }
} }
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, TypedBuilder)]
/// Base argument for object conditional read APIs /// Base argument for object conditional read APIs
pub struct CopySource { pub struct CopySource {
#[builder(default, setter(into))]
pub extra_headers: Option<Multimap>, pub extra_headers: Option<Multimap>,
#[builder(default, setter(into))]
pub extra_query_params: Option<Multimap>, pub extra_query_params: Option<Multimap>,
#[builder(default, setter(into))]
pub region: Option<String>, pub region: Option<String>,
#[builder(setter(into))] // force required + accept Into<String>
pub bucket: String, pub bucket: String,
#[builder(setter(into))] // force required + accept Into<String>
pub object: String, pub object: String,
#[builder(default, setter(into))]
pub version_id: Option<String>, pub version_id: Option<String>,
#[builder(default, setter(into))]
pub ssec: Option<SseCustomerKey>, pub ssec: Option<SseCustomerKey>,
#[builder(default, setter(into))]
pub offset: Option<u64>, pub offset: Option<u64>,
#[builder(default, setter(into))]
pub length: Option<u64>, pub length: Option<u64>,
#[builder(default, setter(into))]
pub match_etag: Option<String>, pub match_etag: Option<String>,
#[builder(default, setter(into))]
pub not_match_etag: Option<String>, pub not_match_etag: Option<String>,
#[builder(default, setter(into))]
pub modified_since: Option<UtcTime>, pub modified_since: Option<UtcTime>,
#[builder(default, setter(into))]
pub unmodified_since: Option<UtcTime>, pub unmodified_since: Option<UtcTime>,
} }
impl CopySource { impl CopySource {
pub fn new(bucket_name: &str, object_name: &str) -> Result<Self, ValidationErr> {
check_bucket_name(bucket_name, true)?;
check_object_name(object_name)?;
Ok(Self {
bucket: bucket_name.to_owned(),
object: object_name.to_owned(),
..Default::default()
})
}
fn get_range_value(&self) -> String { fn get_range_value(&self) -> String {
let (offset, length) = match self.length { let (offset, length) = match self.length {
Some(_) => (Some(self.offset.unwrap_or(0_u64)), self.length), Some(_) => (Some(self.offset.unwrap_or(0_u64)), self.length),

View File

@ -13,8 +13,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::Client;
use crate::s3::client::DEFAULT_REGION; use crate::s3::client::DEFAULT_REGION;
use crate::s3::client::MinioClient;
use crate::s3::error::ValidationErr; use crate::s3::error::ValidationErr;
use crate::s3::header_constants::*; use crate::s3::header_constants::*;
use crate::s3::multimap_ext::{Multimap, MultimapExt}; use crate::s3::multimap_ext::{Multimap, MultimapExt};
@ -23,57 +23,37 @@ use crate::s3::segmented_bytes::SegmentedBytes;
use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::types::{S3Api, S3Request, ToS3Request};
use crate::s3::utils::check_bucket_name; use crate::s3::utils::check_bucket_name;
use http::Method; use http::Method;
use std::sync::Arc;
use typed_builder::TypedBuilder;
/// Argument builder for the [`CreateBucket`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateBucket.html) S3 API operation. /// Argument builder for the [`CreateBucket`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateBucket.html) S3 API operation.
/// ///
/// This struct constructs the parameters required for the [`Client::create_bucket`](crate::s3::client::Client::create_bucket) method. /// This struct constructs the parameters required for the [`Client::create_bucket`](crate::s3::client::MinioClient::create_bucket) method.
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, TypedBuilder)]
pub struct CreateBucket { pub struct CreateBucket {
client: Client, #[builder(!default)] // force required
client: MinioClient,
#[builder(default, setter(into))]
extra_headers: Option<Multimap>, extra_headers: Option<Multimap>,
#[builder(default, setter(into))]
extra_query_params: Option<Multimap>, extra_query_params: Option<Multimap>,
#[builder(default, setter(into))]
region: Option<String>, region: Option<String>,
#[builder(!default, setter(into))] // force required + accept Into<String>
bucket: String, bucket: String,
#[builder(default = false)]
object_lock: bool, object_lock: bool,
} }
impl CreateBucket {
pub fn new(client: Client, bucket: String) -> Self {
Self {
client,
bucket,
..Default::default()
}
}
pub fn extra_headers(mut self, extra_headers: Option<Multimap>) -> Self {
self.extra_headers = extra_headers;
self
}
pub fn extra_query_params(mut self, extra_query_params: Option<Multimap>) -> Self {
self.extra_query_params = extra_query_params;
self
}
/// Sets the region for the request
pub fn region(mut self, region: Option<String>) -> Self {
self.region = region;
self
}
pub fn object_lock(mut self, object_lock: bool) -> Self {
self.object_lock = object_lock;
self
}
}
impl S3Api for CreateBucket { impl S3Api for CreateBucket {
type S3Response = CreateBucketResponse; type S3Response = CreateBucketResponse;
} }
/// Builder type for [`CreateBucket`] that is returned by [`MinioClient::create_bucket`](crate::s3::client::MinioClient::create_bucket).
///
/// This type alias simplifies the complex generic signature generated by the `typed_builder` crate.
pub type CreateBucketBldr = CreateBucketBuilder<((MinioClient,), (), (), (), (String,), ())>;
impl ToS3Request for CreateBucket { impl ToS3Request for CreateBucket {
fn to_s3request(self) -> Result<S3Request, ValidationErr> { fn to_s3request(self) -> Result<S3Request, ValidationErr> {
check_bucket_name(&self.bucket, true)?; check_bucket_name(&self.bucket, true)?;
@ -106,16 +86,19 @@ impl ToS3Request for CreateBucket {
), ),
}; };
let body: Option<SegmentedBytes> = match data.is_empty() { let body: Option<Arc<SegmentedBytes>> = match data.is_empty() {
true => None, true => None,
false => Some(SegmentedBytes::from(data)), false => Some(Arc::new(SegmentedBytes::from(data))),
}; };
Ok(S3Request::new(self.client, Method::PUT) Ok(S3Request::builder()
.region(Some(region_str)) .client(self.client)
.bucket(Some(self.bucket)) .method(Method::PUT)
.region(region_str)
.bucket(self.bucket)
.query_params(self.extra_query_params.unwrap_or_default()) .query_params(self.extra_query_params.unwrap_or_default())
.headers(headers) .headers(headers)
.body(body)) .body(body)
.build())
} }
} }

View File

@ -13,7 +13,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::builders::BucketCommon; use crate::s3::MinioClient;
use crate::s3::builders::{BucketCommon, BucketCommonBuilder};
use crate::s3::error::ValidationErr; use crate::s3::error::ValidationErr;
use crate::s3::response::DeleteBucketResponse; use crate::s3::response::DeleteBucketResponse;
use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::types::{S3Api, S3Request, ToS3Request};
@ -22,26 +23,35 @@ use http::Method;
/// Argument builder for the [`DeleteBucket`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucket.html) S3 API operation. /// Argument builder for the [`DeleteBucket`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucket.html) S3 API operation.
/// ///
/// This struct constructs the parameters required for the [`Client::delete_bucket`](crate::s3::client::Client::delete_bucket) method. /// This struct constructs the parameters required for the [`Client::delete_bucket`](crate::s3::client::MinioClient::delete_bucket) method.
/// See [Amazon S3: Deleting Buckets](https://docs.aws.amazon.com/AmazonS3/latest/userguide/delete-bucket.html) for more information. /// See [Amazon S3: Deleting Buckets](https://docs.aws.amazon.com/AmazonS3/latest/userguide/delete-bucket.html) for more information.
pub type DeleteBucket = BucketCommon<DeleteBucketPhantomData>; pub type DeleteBucket = BucketCommon<DeleteBucketPhantomData>;
#[doc(hidden)] #[doc(hidden)]
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug)]
pub struct DeleteBucketPhantomData; pub struct DeleteBucketPhantomData;
impl S3Api for DeleteBucket { impl S3Api for DeleteBucket {
type S3Response = DeleteBucketResponse; type S3Response = DeleteBucketResponse;
} }
/// Builder type for [`DeleteBucket`] that is returned by [`MinioClient::delete_bucket`](crate::s3::client::MinioClient::delete_bucket).
///
/// This type alias simplifies the complex generic signature generated by the `typed_builder` crate.
pub type DeleteBucketBldr =
BucketCommonBuilder<DeleteBucketPhantomData, ((MinioClient,), (), (), (), (String,), ())>;
impl ToS3Request for DeleteBucket { impl ToS3Request for DeleteBucket {
fn to_s3request(self) -> Result<S3Request, ValidationErr> { fn to_s3request(self) -> Result<S3Request, ValidationErr> {
check_bucket_name(&self.bucket, true)?; check_bucket_name(&self.bucket, true)?;
Ok(S3Request::new(self.client, Method::DELETE) Ok(S3Request::builder()
.client(self.client)
.method(Method::DELETE)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.query_params(self.extra_query_params.unwrap_or_default()) .query_params(self.extra_query_params.unwrap_or_default())
.headers(self.extra_headers.unwrap_or_default())) .headers(self.extra_headers.unwrap_or_default())
.build())
} }
} }

View File

@ -13,7 +13,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::builders::BucketCommon; use crate::s3::MinioClient;
use crate::s3::builders::{BucketCommon, BucketCommonBuilder};
use crate::s3::error::ValidationErr; use crate::s3::error::ValidationErr;
use crate::s3::response::DeleteBucketEncryptionResponse; use crate::s3::response::DeleteBucketEncryptionResponse;
use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::types::{S3Api, S3Request, ToS3Request};
@ -22,25 +23,36 @@ use http::Method;
/// Argument builder for the [`DeleteBucketEncryption`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketEncryption.html) S3 API operation. /// Argument builder for the [`DeleteBucketEncryption`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketEncryption.html) S3 API operation.
/// ///
/// This struct constructs the parameters required for the [`Client::delete_bucket_encryption`](crate::s3::client::Client::delete_bucket_encryption) method. /// This struct constructs the parameters required for the [`Client::delete_bucket_encryption`](crate::s3::client::MinioClient::delete_bucket_encryption) method.
pub type DeleteBucketEncryption = BucketCommon<DeleteBucketEncryptionPhantomData>; pub type DeleteBucketEncryption = BucketCommon<DeleteBucketEncryptionPhantomData>;
#[doc(hidden)] #[doc(hidden)]
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug)]
pub struct DeleteBucketEncryptionPhantomData; pub struct DeleteBucketEncryptionPhantomData;
impl S3Api for DeleteBucketEncryption { impl S3Api for DeleteBucketEncryption {
type S3Response = DeleteBucketEncryptionResponse; type S3Response = DeleteBucketEncryptionResponse;
} }
/// Builder type for [`DeleteBucketEncryption`] that is returned by [`MinioClient::delete_bucket_encryption`](crate::s3::client::MinioClient::delete_bucket_encryption).
///
/// This type alias simplifies the complex generic signature generated by the `typed_builder` crate.
pub type DeleteBucketEncryptionBldr = BucketCommonBuilder<
DeleteBucketEncryptionPhantomData,
((MinioClient,), (), (), (), (String,), ()),
>;
impl ToS3Request for DeleteBucketEncryption { impl ToS3Request for DeleteBucketEncryption {
fn to_s3request(self) -> Result<S3Request, ValidationErr> { fn to_s3request(self) -> Result<S3Request, ValidationErr> {
check_bucket_name(&self.bucket, true)?; check_bucket_name(&self.bucket, true)?;
Ok(S3Request::new(self.client, Method::DELETE) Ok(S3Request::builder()
.client(self.client)
.method(Method::DELETE)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.query_params(insert(self.extra_query_params, "encryption")) .query_params(insert(self.extra_query_params, "encryption"))
.headers(self.extra_headers.unwrap_or_default())) .headers(self.extra_headers.unwrap_or_default())
.build())
} }
} }

View File

@ -13,7 +13,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::builders::BucketCommon; use crate::s3::MinioClient;
use crate::s3::builders::{BucketCommon, BucketCommonBuilder};
use crate::s3::error::ValidationErr; use crate::s3::error::ValidationErr;
use crate::s3::response::DeleteBucketLifecycleResponse; use crate::s3::response::DeleteBucketLifecycleResponse;
use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::types::{S3Api, S3Request, ToS3Request};
@ -22,25 +23,36 @@ use http::Method;
/// Argument builder for the [`DeleteBucketLifecycle`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketLifecycle.html) S3 API operation. /// Argument builder for the [`DeleteBucketLifecycle`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketLifecycle.html) S3 API operation.
/// ///
/// This struct constructs the parameters required for the [`Client::delete_bucket_lifecycle`](crate::s3::client::Client::delete_bucket_lifecycle) method. /// This struct constructs the parameters required for the [`Client::delete_bucket_lifecycle`](crate::s3::client::MinioClient::delete_bucket_lifecycle) method.
pub type DeleteBucketLifecycle = BucketCommon<DeleteBucketLifecyclePhantomData>; pub type DeleteBucketLifecycle = BucketCommon<DeleteBucketLifecyclePhantomData>;
#[doc(hidden)] #[doc(hidden)]
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug)]
pub struct DeleteBucketLifecyclePhantomData; pub struct DeleteBucketLifecyclePhantomData;
impl S3Api for DeleteBucketLifecycle { impl S3Api for DeleteBucketLifecycle {
type S3Response = DeleteBucketLifecycleResponse; type S3Response = DeleteBucketLifecycleResponse;
} }
/// Builder type for [`DeleteBucketLifecycle`] that is returned by [`MinioClient::delete_bucket_lifecycle`](crate::s3::client::MinioClient::delete_bucket_lifecycle).
///
/// This type alias simplifies the complex generic signature generated by the `typed_builder` crate.
pub type DeleteBucketLifecycleBldr = BucketCommonBuilder<
DeleteBucketLifecyclePhantomData,
((MinioClient,), (), (), (), (String,), ()),
>;
impl ToS3Request for DeleteBucketLifecycle { impl ToS3Request for DeleteBucketLifecycle {
fn to_s3request(self) -> Result<S3Request, ValidationErr> { fn to_s3request(self) -> Result<S3Request, ValidationErr> {
check_bucket_name(&self.bucket, true)?; check_bucket_name(&self.bucket, true)?;
Ok(S3Request::new(self.client, Method::DELETE) Ok(S3Request::builder()
.client(self.client)
.method(Method::DELETE)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.query_params(insert(self.extra_query_params, "lifecycle")) .query_params(insert(self.extra_query_params, "lifecycle"))
.headers(self.extra_headers.unwrap_or_default())) .headers(self.extra_headers.unwrap_or_default())
.build())
} }
} }

View File

@ -13,7 +13,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::builders::BucketCommon; use crate::s3::MinioClient;
use crate::s3::builders::{BucketCommon, BucketCommonBuilder};
use crate::s3::error::ValidationErr; use crate::s3::error::ValidationErr;
use crate::s3::response::DeleteBucketNotificationResponse; use crate::s3::response::DeleteBucketNotificationResponse;
use crate::s3::segmented_bytes::SegmentedBytes; use crate::s3::segmented_bytes::SegmentedBytes;
@ -21,22 +22,31 @@ use crate::s3::types::{NotificationConfig, S3Api, S3Request, ToS3Request};
use crate::s3::utils::{check_bucket_name, insert}; use crate::s3::utils::{check_bucket_name, insert};
use bytes::Bytes; use bytes::Bytes;
use http::Method; use http::Method;
use std::sync::Arc;
/// Argument builder for the [`DeleteBucketNotification`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketNotificationConfiguration.html) S3 API operation. /// Argument builder for the [`DeleteBucketNotification`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketNotificationConfiguration.html) S3 API operation.
/// Note: on Amazon S3, a bucket notification is deleted by setting its configuration to empty. /// Note: on Amazon S3, a bucket notification is deleted by setting its configuration to empty.
/// ///
/// This struct constructs the parameters required for the [`Client::delete_bucket_notification`](crate::s3::client::Client::delete_bucket_notification) method. /// This struct constructs the parameters required for the [`Client::delete_bucket_notification`](crate::s3::client::MinioClient::delete_bucket_notification) method.
/// See [Amazon S3: Managing Bucket Notifications](https://docs.aws.amazon.com/AmazonS3/latest/userguide/NotificationHowTo.html) for more information. /// See [Amazon S3: Managing Bucket Notifications](https://docs.aws.amazon.com/AmazonS3/latest/userguide/NotificationHowTo.html) for more information.
pub type DeleteBucketNotification = BucketCommon<DeleteBucketNotificationPhantomData>; pub type DeleteBucketNotification = BucketCommon<DeleteBucketNotificationPhantomData>;
#[doc(hidden)] #[doc(hidden)]
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug)]
pub struct DeleteBucketNotificationPhantomData; pub struct DeleteBucketNotificationPhantomData;
impl S3Api for DeleteBucketNotification { impl S3Api for DeleteBucketNotification {
type S3Response = DeleteBucketNotificationResponse; type S3Response = DeleteBucketNotificationResponse;
} }
/// Builder type for [`DeleteBucketNotification`] that is returned by [`MinioClient::delete_bucket_notification`](crate::s3::client::MinioClient::delete_bucket_notification).
///
/// This type alias simplifies the complex generic signature generated by the `typed_builder` crate.
pub type DeleteBucketNotificationBldr = BucketCommonBuilder<
DeleteBucketNotificationPhantomData,
((MinioClient,), (), (), (), (String,), ()),
>;
impl ToS3Request for DeleteBucketNotification { impl ToS3Request for DeleteBucketNotification {
fn to_s3request(self) -> Result<S3Request, ValidationErr> { fn to_s3request(self) -> Result<S3Request, ValidationErr> {
check_bucket_name(&self.bucket, true)?; check_bucket_name(&self.bucket, true)?;
@ -47,14 +57,17 @@ impl ToS3Request for DeleteBucketNotification {
topic_config_list: None, topic_config_list: None,
}; };
let bytes: Bytes = CONFIG.to_xml().into(); let bytes: Bytes = CONFIG.to_xml().into();
let body: Option<SegmentedBytes> = Some(SegmentedBytes::from(bytes)); let body: Arc<SegmentedBytes> = Arc::new(SegmentedBytes::from(bytes));
//TODO consider const body //TODO consider const body
Ok(S3Request::new(self.client, Method::PUT) Ok(S3Request::builder()
.client(self.client)
.method(Method::PUT)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.query_params(insert(self.extra_query_params, "notification")) .query_params(insert(self.extra_query_params, "notification"))
.headers(self.extra_headers.unwrap_or_default()) .headers(self.extra_headers.unwrap_or_default())
.body(body)) .body(body)
.build())
} }
} }

View File

@ -13,7 +13,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::builders::BucketCommon; use crate::s3::MinioClient;
use crate::s3::builders::{BucketCommon, BucketCommonBuilder};
use crate::s3::error::ValidationErr; use crate::s3::error::ValidationErr;
use crate::s3::response::DeleteBucketPolicyResponse; use crate::s3::response::DeleteBucketPolicyResponse;
use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::types::{S3Api, S3Request, ToS3Request};
@ -22,25 +23,34 @@ use http::Method;
/// Argument builder for the [`DeleteBucketPolicy`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketPolicy.html) S3 API operation. /// Argument builder for the [`DeleteBucketPolicy`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketPolicy.html) S3 API operation.
/// ///
/// This struct constructs the parameters required for the [`Client::delete_bucket_policy`](crate::s3::client::Client::delete_bucket_policy) method. /// This struct constructs the parameters required for the [`Client::delete_bucket_policy`](crate::s3::client::MinioClient::delete_bucket_policy) method.
pub type DeleteBucketPolicy = BucketCommon<DeleteBucketPolicyPhantomData>; pub type DeleteBucketPolicy = BucketCommon<DeleteBucketPolicyPhantomData>;
#[doc(hidden)] #[doc(hidden)]
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug)]
pub struct DeleteBucketPolicyPhantomData; pub struct DeleteBucketPolicyPhantomData;
impl S3Api for DeleteBucketPolicy { impl S3Api for DeleteBucketPolicy {
type S3Response = DeleteBucketPolicyResponse; type S3Response = DeleteBucketPolicyResponse;
} }
/// Builder type for [`DeleteBucketPolicy`] that is returned by [`MinioClient::delete_bucket_policy`](crate::s3::client::MinioClient::delete_bucket_policy).
///
/// This type alias simplifies the complex generic signature generated by the `typed_builder` crate.
pub type DeleteBucketPolicyBldr =
BucketCommonBuilder<DeleteBucketPolicyPhantomData, ((MinioClient,), (), (), (), (String,), ())>;
impl ToS3Request for DeleteBucketPolicy { impl ToS3Request for DeleteBucketPolicy {
fn to_s3request(self) -> Result<S3Request, ValidationErr> { fn to_s3request(self) -> Result<S3Request, ValidationErr> {
check_bucket_name(&self.bucket, true)?; check_bucket_name(&self.bucket, true)?;
Ok(S3Request::new(self.client, Method::DELETE) Ok(S3Request::builder()
.client(self.client)
.method(Method::DELETE)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.query_params(insert(self.extra_query_params, "policy")) .query_params(insert(self.extra_query_params, "policy"))
.headers(self.extra_headers.unwrap_or_default())) .headers(self.extra_headers.unwrap_or_default())
.build())
} }
} }

View File

@ -13,7 +13,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::builders::BucketCommon; use crate::s3::MinioClient;
use crate::s3::builders::{BucketCommon, BucketCommonBuilder};
use crate::s3::error::ValidationErr; use crate::s3::error::ValidationErr;
use crate::s3::response::DeleteBucketReplicationResponse; use crate::s3::response::DeleteBucketReplicationResponse;
use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::types::{S3Api, S3Request, ToS3Request};
@ -22,25 +23,36 @@ use http::Method;
/// Argument builder for the [`DeleteBucketReplication`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketReplication.html) S3 API operation. /// Argument builder for the [`DeleteBucketReplication`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketReplication.html) S3 API operation.
/// ///
/// This struct constructs the parameters required for the [`Client::delete_bucket_replication`](crate::s3::client::Client::delete_bucket_replication) method. /// This struct constructs the parameters required for the [`Client::delete_bucket_replication`](crate::s3::client::MinioClient::delete_bucket_replication) method.
pub type DeleteBucketReplication = BucketCommon<DeleteBucketReplicationPhantomData>; pub type DeleteBucketReplication = BucketCommon<DeleteBucketReplicationPhantomData>;
#[doc(hidden)] #[doc(hidden)]
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug)]
pub struct DeleteBucketReplicationPhantomData; pub struct DeleteBucketReplicationPhantomData;
impl S3Api for DeleteBucketReplication { impl S3Api for DeleteBucketReplication {
type S3Response = DeleteBucketReplicationResponse; type S3Response = DeleteBucketReplicationResponse;
} }
/// Builder type for [`DeleteBucketReplication`] that is returned by [`MinioClient::delete_bucket_replication`](crate::s3::client::MinioClient::delete_bucket_replication).
///
/// This type alias simplifies the complex generic signature generated by the `typed_builder` crate.
pub type DeleteBucketReplicationBldr = BucketCommonBuilder<
DeleteBucketReplicationPhantomData,
((MinioClient,), (), (), (), (String,), ()),
>;
impl ToS3Request for DeleteBucketReplication { impl ToS3Request for DeleteBucketReplication {
fn to_s3request(self) -> Result<S3Request, ValidationErr> { fn to_s3request(self) -> Result<S3Request, ValidationErr> {
check_bucket_name(&self.bucket, true)?; check_bucket_name(&self.bucket, true)?;
Ok(S3Request::new(self.client, Method::DELETE) Ok(S3Request::builder()
.client(self.client)
.method(Method::DELETE)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.query_params(insert(self.extra_query_params, "replication")) .query_params(insert(self.extra_query_params, "replication"))
.headers(self.extra_headers.unwrap_or_default())) .headers(self.extra_headers.unwrap_or_default())
.build())
} }
} }

View File

@ -13,7 +13,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::builders::BucketCommon; use crate::s3::MinioClient;
use crate::s3::builders::{BucketCommon, BucketCommonBuilder};
use crate::s3::error::ValidationErr; use crate::s3::error::ValidationErr;
use crate::s3::response::DeleteBucketTaggingResponse; use crate::s3::response::DeleteBucketTaggingResponse;
use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::types::{S3Api, S3Request, ToS3Request};
@ -22,25 +23,35 @@ use http::Method;
/// Argument builder for the [`DeleteBucketTagging`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketTagging.html) S3 API operation. /// Argument builder for the [`DeleteBucketTagging`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketTagging.html) S3 API operation.
/// ///
/// This struct constructs the parameters required for the [`Client::delete_bucket_tags`](crate::s3::client::Client::delete_bucket_tagging) method. /// This struct constructs the parameters required for the [`Client::delete_bucket_tags`](crate::s3::client::MinioClient::delete_bucket_tagging) method.
pub type DeleteBucketTagging = BucketCommon<DeleteBucketTaggingPhantomData>; pub type DeleteBucketTagging = BucketCommon<DeleteBucketTaggingPhantomData>;
#[doc(hidden)] #[doc(hidden)]
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug)]
pub struct DeleteBucketTaggingPhantomData; pub struct DeleteBucketTaggingPhantomData;
impl S3Api for DeleteBucketTagging { impl S3Api for DeleteBucketTagging {
type S3Response = DeleteBucketTaggingResponse; type S3Response = DeleteBucketTaggingResponse;
} }
/// Builder type for [`DeleteBucketTagging`] that is returned by [`MinioClient::delete_bucket_tagging`](crate::s3::client::MinioClient::delete_bucket_tagging).
///
/// This type alias simplifies the complex generic signature generated by the `typed_builder` crate.
pub type DeleteBucketTaggingBldr = BucketCommonBuilder<
DeleteBucketTaggingPhantomData,
((MinioClient,), (), (), (), (String,), ()),
>;
impl ToS3Request for DeleteBucketTagging { impl ToS3Request for DeleteBucketTagging {
fn to_s3request(self) -> Result<S3Request, ValidationErr> { fn to_s3request(self) -> Result<S3Request, ValidationErr> {
check_bucket_name(&self.bucket, true)?; check_bucket_name(&self.bucket, true)?;
Ok(S3Request::new(self.client, Method::DELETE) Ok(S3Request::builder()
.region(self.region) .client(self.client)
.bucket(Some(self.bucket)) .method(Method::DELETE)
.bucket(self.bucket)
.query_params(insert(self.extra_query_params, "tagging")) .query_params(insert(self.extra_query_params, "tagging"))
.headers(self.extra_headers.unwrap_or_default())) .headers(self.extra_headers.unwrap_or_default())
.build())
} }
} }

View File

@ -13,7 +13,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::builders::BucketCommon; use crate::s3::MinioClient;
use crate::s3::builders::{BucketCommon, BucketCommonBuilder};
use crate::s3::error::ValidationErr; use crate::s3::error::ValidationErr;
use crate::s3::response::DeleteObjectLockConfigResponse; use crate::s3::response::DeleteObjectLockConfigResponse;
use crate::s3::segmented_bytes::SegmentedBytes; use crate::s3::segmented_bytes::SegmentedBytes;
@ -21,18 +22,27 @@ use crate::s3::types::{ObjectLockConfig, S3Api, S3Request, ToS3Request};
use crate::s3::utils::{check_bucket_name, insert}; use crate::s3::utils::{check_bucket_name, insert};
use bytes::Bytes; use bytes::Bytes;
use http::Method; use http::Method;
use std::sync::Arc;
/// This struct constructs the parameters required for the [`Client::delete_object_lock_config`](crate::s3::client::Client::delete_object_lock_config) method. /// This struct constructs the parameters required for the [`Client::delete_object_lock_config`](crate::s3::client::MinioClient::delete_object_lock_config) method.
pub type DeleteObjectLockConfig = BucketCommon<DeleteObjectLockConfigPhantomData>; pub type DeleteObjectLockConfig = BucketCommon<DeleteObjectLockConfigPhantomData>;
#[doc(hidden)] #[doc(hidden)]
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug)]
pub struct DeleteObjectLockConfigPhantomData; pub struct DeleteObjectLockConfigPhantomData;
impl S3Api for DeleteObjectLockConfig { impl S3Api for DeleteObjectLockConfig {
type S3Response = DeleteObjectLockConfigResponse; type S3Response = DeleteObjectLockConfigResponse;
} }
/// Builder type for [`DeleteObjectLockConfig`] that is returned by [`MinioClient::delete_object_lock_config`](crate::s3::client::MinioClient::delete_object_lock_config).
///
/// This type alias simplifies the complex generic signature generated by the `typed_builder` crate.
pub type DeleteObjectLockConfigBldr = BucketCommonBuilder<
DeleteObjectLockConfigPhantomData,
((MinioClient,), (), (), (), (String,), ()),
>;
impl ToS3Request for DeleteObjectLockConfig { impl ToS3Request for DeleteObjectLockConfig {
fn to_s3request(self) -> Result<S3Request, ValidationErr> { fn to_s3request(self) -> Result<S3Request, ValidationErr> {
check_bucket_name(&self.bucket, true)?; check_bucket_name(&self.bucket, true)?;
@ -43,14 +53,17 @@ impl ToS3Request for DeleteObjectLockConfig {
retention_duration_years: None, retention_duration_years: None,
}; };
let bytes: Bytes = config.to_xml().into(); let bytes: Bytes = config.to_xml().into();
let body: Option<SegmentedBytes> = Some(SegmentedBytes::from(bytes)); let body: Arc<SegmentedBytes> = Arc::new(SegmentedBytes::from(bytes));
//TODO consider const body //TODO consider const body
Ok(S3Request::new(self.client, Method::PUT) Ok(S3Request::builder()
.client(self.client)
.method(Method::PUT)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.query_params(insert(self.extra_query_params, "object-lock")) .query_params(insert(self.extra_query_params, "object-lock"))
.headers(self.extra_headers.unwrap_or_default()) .headers(self.extra_headers.unwrap_or_default())
.body(body)) .body(body)
.build())
} }
} }

View File

@ -13,66 +13,46 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::Client; use crate::s3::client::MinioClient;
use crate::s3::error::ValidationErr; use crate::s3::error::ValidationErr;
use crate::s3::multimap_ext::{Multimap, MultimapExt}; use crate::s3::multimap_ext::{Multimap, MultimapExt};
use crate::s3::response::DeleteObjectTaggingResponse; use crate::s3::response::DeleteObjectTaggingResponse;
use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::types::{S3Api, S3Request, ToS3Request};
use crate::s3::utils::{check_bucket_name, check_object_name, insert}; use crate::s3::utils::{check_bucket_name, check_object_name, insert};
use http::Method; use http::Method;
use typed_builder::TypedBuilder;
/// Argument builder for the [`DeleteObjectTagging`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObjectTagging.html) S3 API operation. /// Argument builder for the [`DeleteObjectTagging`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObjectTagging.html) S3 API operation.
/// ///
/// This struct constructs the parameters required for the [`Client::delete_object_tags`](crate::s3::client::Client::delete_object_tagging) method. /// This struct constructs the parameters required for the [`Client::delete_object_tags`](crate::s3::client::MinioClient::delete_object_tagging) method.
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, TypedBuilder)]
pub struct DeleteObjectTagging { pub struct DeleteObjectTagging {
client: Client, #[builder(!default)] // force required
client: MinioClient,
#[builder(default, setter(into))]
extra_headers: Option<Multimap>, extra_headers: Option<Multimap>,
#[builder(default, setter(into))]
extra_query_params: Option<Multimap>, extra_query_params: Option<Multimap>,
#[builder(default, setter(into))]
region: Option<String>, region: Option<String>,
#[builder(setter(into))] // force required + accept Into<String>
bucket: String, bucket: String,
#[builder(setter(into))] // force required + accept Into<String>
object: String, object: String,
#[builder(default, setter(into))]
version_id: Option<String>, version_id: Option<String>,
} }
impl DeleteObjectTagging {
pub fn new(client: Client, bucket: String, object: String) -> Self {
Self {
client,
bucket,
object,
..Default::default()
}
}
pub fn extra_headers(mut self, extra_headers: Option<Multimap>) -> Self {
self.extra_headers = extra_headers;
self
}
pub fn extra_query_params(mut self, extra_query_params: Option<Multimap>) -> Self {
self.extra_query_params = extra_query_params;
self
}
/// Sets the region for the request
pub fn region(mut self, region: Option<String>) -> Self {
self.region = region;
self
}
pub fn version_id(mut self, version_id: Option<String>) -> Self {
self.version_id = version_id;
self
}
}
impl S3Api for DeleteObjectTagging { impl S3Api for DeleteObjectTagging {
type S3Response = DeleteObjectTaggingResponse; type S3Response = DeleteObjectTaggingResponse;
} }
/// Builder type for [`DeleteObjectTagging`] that is returned by [`MinioClient::delete_object_tagging`](crate::s3::client::MinioClient::delete_object_tagging).
///
/// This type alias simplifies the complex generic signature generated by the `typed_builder` crate.
pub type DeleteObjectTaggingBldr =
DeleteObjectTaggingBuilder<((MinioClient,), (), (), (), (String,), (String,), ())>;
impl ToS3Request for DeleteObjectTagging { impl ToS3Request for DeleteObjectTagging {
fn to_s3request(self) -> Result<S3Request, ValidationErr> { fn to_s3request(self) -> Result<S3Request, ValidationErr> {
check_bucket_name(&self.bucket, true)?; check_bucket_name(&self.bucket, true)?;
@ -81,11 +61,14 @@ impl ToS3Request for DeleteObjectTagging {
let mut query_params: Multimap = insert(self.extra_query_params, "tagging"); let mut query_params: Multimap = insert(self.extra_query_params, "tagging");
query_params.add_version(self.version_id); query_params.add_version(self.version_id);
Ok(S3Request::new(self.client, Method::DELETE) Ok(S3Request::builder()
.client(self.client)
.method(Method::DELETE)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.query_params(query_params) .query_params(query_params)
.object(Some(self.object)) .object(self.object)
.headers(self.extra_headers.unwrap_or_default())) .headers(self.extra_headers.unwrap_or_default())
.build())
} }
} }

View File

@ -13,12 +13,13 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::Client;
use crate::s3::client::MAX_MULTIPART_COUNT; use crate::s3::client::MAX_MULTIPART_COUNT;
use crate::s3::client::MinioClient;
use crate::s3::error::{Error, ValidationErr}; use crate::s3::error::{Error, ValidationErr};
use crate::s3::header_constants::*; use crate::s3::header_constants::*;
use crate::s3::multimap_ext::{Multimap, MultimapExt}; use crate::s3::multimap_ext::{Multimap, MultimapExt};
use crate::s3::response::{DeleteError, DeleteObjectResponse, DeleteObjectsResponse}; use crate::s3::response::{DeleteError, DeleteObjectResponse, DeleteObjectsResponse};
use crate::s3::segmented_bytes::SegmentedBytes;
use crate::s3::types::{ListEntry, S3Api, S3Request, ToS3Request, ToStream}; use crate::s3::types::{ListEntry, S3Api, S3Request, ToS3Request, ToStream};
use crate::s3::utils::{check_bucket_name, check_object_name, insert, md5sum_hash}; use crate::s3::utils::{check_bucket_name, check_object_name, insert, md5sum_hash};
use async_trait::async_trait; use async_trait::async_trait;
@ -27,6 +28,8 @@ use futures_util::stream::iter;
use futures_util::{Stream, StreamExt, stream as futures_stream}; use futures_util::{Stream, StreamExt, stream as futures_stream};
use http::Method; use http::Method;
use std::pin::Pin; use std::pin::Pin;
use std::sync::Arc;
use typed_builder::TypedBuilder;
// region: object-to-delete // region: object-to-delete
pub trait ValidKey: Into<String> {} pub trait ValidKey: Into<String> {}
@ -94,58 +97,37 @@ impl From<DeleteError> for ObjectToDelete {
// region: delete-object // region: delete-object
/// Argument builder for the [`RemoveObject`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObject.html) S3 API operation. /// Argument builder for the [`DeleteObject`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObject.html) S3 API operation.
/// ///
/// This struct constructs the parameters required for the [`Client::remove_object`](crate::s3::client::Client::delete_object) method. /// This struct constructs the parameters required for the [`Client::delete_object`](crate::s3::client::Client::delete_object) method.
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, TypedBuilder)]
pub struct DeleteObject { pub struct DeleteObject {
client: Client, #[builder(!default)] // force required
client: MinioClient,
#[builder(default, setter(into))]
extra_headers: Option<Multimap>, extra_headers: Option<Multimap>,
#[builder(default, setter(into))]
extra_query_params: Option<Multimap>, extra_query_params: Option<Multimap>,
#[builder(default, setter(into))]
region: Option<String>, region: Option<String>,
#[builder(setter(into))] // force required + accept Into<String>
bucket: String, bucket: String,
#[builder(default, setter(into))]
object: ObjectToDelete, object: ObjectToDelete,
#[builder(default)]
bypass_governance_mode: bool, bypass_governance_mode: bool,
} }
impl DeleteObject {
pub fn new(client: Client, bucket: String, object: impl Into<ObjectToDelete>) -> Self {
Self {
client,
bucket,
object: object.into(),
..Default::default()
}
}
pub fn bypass_governance_mode(mut self, bypass_governance_mode: bool) -> Self {
self.bypass_governance_mode = bypass_governance_mode;
self
}
pub fn extra_headers(mut self, extra_headers: Option<Multimap>) -> Self {
self.extra_headers = extra_headers;
self
}
pub fn extra_query_params(mut self, extra_query_params: Option<Multimap>) -> Self {
self.extra_query_params = extra_query_params;
self
}
/// Sets the region for the request
pub fn region(mut self, region: Option<String>) -> Self {
self.region = region;
self
}
}
impl S3Api for DeleteObject { impl S3Api for DeleteObject {
type S3Response = DeleteObjectResponse; type S3Response = DeleteObjectResponse;
} }
/// Builder type for [`DeleteObject`] that is returned by [`MinioClient::delete_object`](crate::s3::client::MinioClient::delete_object).
///
/// This type alias simplifies the complex generic signature generated by the `typed_builder` crate.
pub type DeleteObjectBldr =
DeleteObjectBuilder<((MinioClient,), (), (), (), (String,), (ObjectToDelete,), ())>;
impl ToS3Request for DeleteObject { impl ToS3Request for DeleteObject {
fn to_s3request(self) -> Result<S3Request, ValidationErr> { fn to_s3request(self) -> Result<S3Request, ValidationErr> {
check_bucket_name(&self.bucket, true)?; check_bucket_name(&self.bucket, true)?;
@ -159,77 +141,68 @@ impl ToS3Request for DeleteObject {
headers.add(X_AMZ_BYPASS_GOVERNANCE_RETENTION, "true"); headers.add(X_AMZ_BYPASS_GOVERNANCE_RETENTION, "true");
} }
Ok(S3Request::new(self.client, Method::DELETE) Ok(S3Request::builder()
.client(self.client)
.method(Method::DELETE)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.object(Some(self.object.key)) .object(self.object.key)
.query_params(query_params) .query_params(query_params)
.headers(headers)) .headers(headers)
.build())
} }
} }
// endregion: delete-object // endregion: delete-object
// region: delete-objects // region: delete-objects
#[derive(Debug, Clone, Default)]
/// Argument builder for the [`DeleteObjects`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObjects.html) S3 API operation.
///
/// This struct constructs the parameters required for the [`Client::delete_objects`](crate::s3::client::Client::delete_objects) method.
#[derive(Clone, Debug, TypedBuilder)]
pub struct DeleteObjects { pub struct DeleteObjects {
client: Client, #[builder(!default)] // force required
client: MinioClient,
bucket: String, #[builder(default, setter(into))]
objects: Vec<ObjectToDelete>,
bypass_governance_mode: bool,
verbose_mode: bool,
extra_headers: Option<Multimap>, extra_headers: Option<Multimap>,
#[builder(default, setter(into))]
extra_query_params: Option<Multimap>, extra_query_params: Option<Multimap>,
#[builder(default, setter(into))]
region: Option<String>, region: Option<String>,
} #[builder(setter(into))] // force required + accept Into<String>
bucket: String,
impl DeleteObjects { #[builder(!default)]
pub fn new(client: Client, bucket: String, objects: Vec<ObjectToDelete>) -> Self { objects: Vec<ObjectToDelete>,
DeleteObjects { #[builder(default)]
client, bypass_governance_mode: bool,
bucket,
objects,
..Default::default()
}
}
pub fn bypass_governance_mode(mut self, bypass_governance_mode: bool) -> Self {
self.bypass_governance_mode = bypass_governance_mode;
self
}
/// Enable verbose mode (defaults to false). If enabled, the response will /// Enable verbose mode (defaults to false). If enabled, the response will
/// include the keys of objects that were successfully deleted. Otherwise, /// include the keys of objects that were successfully deleted. Otherwise,
/// only objects that encountered an error are returned. /// only objects that encountered an error are returned.
pub fn verbose_mode(mut self, verbose_mode: bool) -> Self { #[builder(default)]
self.verbose_mode = verbose_mode; verbose_mode: bool,
self
}
pub fn extra_headers(mut self, extra_headers: Option<Multimap>) -> Self {
self.extra_headers = extra_headers;
self
}
pub fn extra_query_params(mut self, extra_query_params: Option<Multimap>) -> Self {
self.extra_query_params = extra_query_params;
self
}
/// Sets the region for the request
pub fn region(mut self, region: Option<String>) -> Self {
self.region = region;
self
}
} }
impl S3Api for DeleteObjects { impl S3Api for DeleteObjects {
type S3Response = DeleteObjectsResponse; type S3Response = DeleteObjectsResponse;
} }
/// Builder type for [`DeleteObjects`] that is returned by [`MinioClient::delete_objects`](crate::s3::client::MinioClient::delete_objects).
///
/// This type alias simplifies the complex generic signature generated by the `typed_builder` crate.
pub type DeleteObjectsBldr = DeleteObjectsBuilder<(
(MinioClient,),
(),
(),
(),
(String,),
(Vec<ObjectToDelete>,),
(),
(),
)>;
impl ToS3Request for DeleteObjects { impl ToS3Request for DeleteObjects {
fn to_s3request(self) -> Result<S3Request, ValidationErr> { fn to_s3request(self) -> Result<S3Request, ValidationErr> {
check_bucket_name(&self.bucket, true)?; check_bucket_name(&self.bucket, true)?;
@ -261,13 +234,17 @@ impl ToS3Request for DeleteObjects {
headers.add(CONTENT_TYPE, "application/xml"); headers.add(CONTENT_TYPE, "application/xml");
headers.add(CONTENT_MD5, md5sum_hash(bytes.as_ref())); headers.add(CONTENT_MD5, md5sum_hash(bytes.as_ref()));
} }
let body = Arc::new(SegmentedBytes::from(bytes));
Ok(S3Request::new(self.client, Method::POST) Ok(S3Request::builder()
.client(self.client)
.method(Method::POST)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.query_params(insert(self.extra_query_params, "delete")) .query_params(insert(self.extra_query_params, "delete"))
.headers(headers) .headers(headers)
.body(Some(bytes.into()))) .body(body)
.build())
} }
} }
@ -304,12 +281,12 @@ where
// region: delete-objects-streaming // region: delete-objects-streaming
/// Argument builder for the [`DeleteObjectsStreaming`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObjects.html) S3 API operation. /// Argument builder for streaming multiple object deletions using the [`DeleteObjects`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObjects.html) S3 API operation.
/// Note that this API is not part of the official S3 API, but is a MinIO extension for streaming deletion of multiple objects.
/// ///
/// This struct constructs the parameters required for the [`Client::`](crate::s3::client::Client::get_bucket_encryption) method. /// This struct constructs the parameters required for the [`Client::delete_objects_streaming`](crate::s3::client::Client::delete_objects_streaming) method.
pub struct DeleteObjectsStreaming { pub struct DeleteObjectsStreaming {
client: Client, //TODO
client: MinioClient,
bucket: String, bucket: String,
objects: ObjectsStream, objects: ObjectsStream,
@ -323,7 +300,7 @@ pub struct DeleteObjectsStreaming {
} }
impl DeleteObjectsStreaming { impl DeleteObjectsStreaming {
pub fn new(client: Client, bucket: String, objects: impl Into<ObjectsStream>) -> Self { pub fn new(client: MinioClient, bucket: String, objects: impl Into<ObjectsStream>) -> Self {
Self { Self {
client, client,
bucket, bucket,
@ -380,12 +357,16 @@ impl DeleteObjectsStreaming {
} }
Ok(Some( Ok(Some(
DeleteObjects::new(self.client.clone(), self.bucket.clone(), objects) DeleteObjects::builder()
.client(self.client.clone())
.bucket(self.bucket.clone())
.objects(objects)
.bypass_governance_mode(self.bypass_governance_mode) .bypass_governance_mode(self.bypass_governance_mode)
.verbose_mode(self.verbose_mode) .verbose_mode(self.verbose_mode)
.extra_headers(self.extra_headers.clone()) .extra_headers(self.extra_headers.clone())
.extra_query_params(self.extra_query_params.clone()) .extra_query_params(self.extra_query_params.clone())
.region(self.region.clone()), .region(self.region.clone())
.build(),
)) ))
} }
} }

View File

@ -13,7 +13,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::builders::BucketCommon; use crate::s3::MinioClient;
use crate::s3::builders::{BucketCommon, BucketCommonBuilder};
use crate::s3::error::ValidationErr; use crate::s3::error::ValidationErr;
use crate::s3::response::GetBucketEncryptionResponse; use crate::s3::response::GetBucketEncryptionResponse;
use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::types::{S3Api, S3Request, ToS3Request};
@ -22,25 +23,36 @@ use http::Method;
/// Argument builder for the [`GetBucketEncryption`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketEncryption.html) S3 API operation. /// Argument builder for the [`GetBucketEncryption`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketEncryption.html) S3 API operation.
/// ///
/// This struct constructs the parameters required for the [`Client::get_bucket_encryption`](crate::s3::client::Client::get_bucket_encryption) method. /// This struct constructs the parameters required for the [`Client::get_bucket_encryption`](crate::s3::client::MinioClient::get_bucket_encryption) method.
pub type GetBucketEncryption = BucketCommon<GetBucketEncryptionPhantomData>; pub type GetBucketEncryption = BucketCommon<GetBucketEncryptionPhantomData>;
#[doc(hidden)] #[doc(hidden)]
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug)]
pub struct GetBucketEncryptionPhantomData; pub struct GetBucketEncryptionPhantomData;
impl S3Api for GetBucketEncryption { impl S3Api for GetBucketEncryption {
type S3Response = GetBucketEncryptionResponse; type S3Response = GetBucketEncryptionResponse;
} }
/// Builder type for [`GetBucketEncryption`] that is returned by [`MinioClient::get_bucket_encryption`](crate::s3::client::MinioClient::get_bucket_encryption).
///
/// This type alias simplifies the complex generic signature generated by the `typed_builder` crate.
pub type GetBucketEncryptionBldr = BucketCommonBuilder<
GetBucketEncryptionPhantomData,
((MinioClient,), (), (), (), (String,), ()),
>;
impl ToS3Request for GetBucketEncryption { impl ToS3Request for GetBucketEncryption {
fn to_s3request(self) -> Result<S3Request, ValidationErr> { fn to_s3request(self) -> Result<S3Request, ValidationErr> {
check_bucket_name(&self.bucket, true)?; check_bucket_name(&self.bucket, true)?;
Ok(S3Request::new(self.client, Method::GET) Ok(S3Request::builder()
.client(self.client)
.method(Method::GET)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.query_params(insert(self.extra_query_params, "encryption")) .query_params(insert(self.extra_query_params, "encryption"))
.headers(self.extra_headers.unwrap_or_default())) .headers(self.extra_headers.unwrap_or_default())
.build())
} }
} }

View File

@ -13,58 +13,44 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::Client; use crate::s3::client::MinioClient;
use crate::s3::error::ValidationErr; use crate::s3::error::ValidationErr;
use crate::s3::multimap_ext::{Multimap, MultimapExt}; use crate::s3::multimap_ext::{Multimap, MultimapExt};
use crate::s3::response::GetBucketLifecycleResponse; use crate::s3::response::GetBucketLifecycleResponse;
use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::types::{S3Api, S3Request, ToS3Request};
use crate::s3::utils::{check_bucket_name, insert}; use crate::s3::utils::{check_bucket_name, insert};
use http::Method; use http::Method;
use typed_builder::TypedBuilder;
/// Argument builder for the [`GetBucketLifecycle`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketLifecycle.html) S3 API operation. /// Argument builder for the [`GetBucketLifecycle`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketLifecycle.html) S3 API operation.
/// ///
/// This struct constructs the parameters required for the [`Client::get_bucket_lifecycle`](crate::s3::client::Client::get_bucket_lifecycle) method. /// This struct constructs the parameters required for the [`Client::get_bucket_lifecycle`](crate::s3::client::MinioClient::get_bucket_lifecycle) method.
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, TypedBuilder)]
pub struct GetBucketLifecycle { pub struct GetBucketLifecycle {
client: Client, #[builder(!default)] // force required
client: MinioClient,
#[builder(default, setter(into))]
extra_headers: Option<Multimap>, extra_headers: Option<Multimap>,
#[builder(default, setter(into))]
extra_query_params: Option<Multimap>, extra_query_params: Option<Multimap>,
#[builder(default, setter(into))]
region: Option<String>, region: Option<String>,
#[builder(setter(into))] // force required + accept Into<String>
bucket: String, bucket: String,
#[builder(default)]
with_updated_at: bool, with_updated_at: bool,
} }
impl GetBucketLifecycle {
pub fn new(client: Client, bucket: String) -> Self {
Self {
client,
bucket,
..Default::default()
}
}
pub fn extra_headers(mut self, extra_headers: Option<Multimap>) -> Self {
self.extra_headers = extra_headers;
self
}
pub fn extra_query_params(mut self, extra_query_params: Option<Multimap>) -> Self {
self.extra_query_params = extra_query_params;
self
}
pub fn with_updated_at(mut self, with_updated_at: bool) -> Self {
self.with_updated_at = with_updated_at;
self
}
}
impl S3Api for GetBucketLifecycle { impl S3Api for GetBucketLifecycle {
type S3Response = GetBucketLifecycleResponse; type S3Response = GetBucketLifecycleResponse;
} }
/// Builder type for [`GetBucketLifecycle`] that is returned by [`MinioClient::get_bucket_lifecycle`](crate::s3::client::MinioClient::get_bucket_lifecycle).
///
/// This type alias simplifies the complex generic signature generated by the `typed_builder` crate.
pub type GetBucketLifecycleBldr =
GetBucketLifecycleBuilder<((MinioClient,), (), (), (), (String,), ())>;
impl ToS3Request for GetBucketLifecycle { impl ToS3Request for GetBucketLifecycle {
fn to_s3request(self) -> Result<S3Request, ValidationErr> { fn to_s3request(self) -> Result<S3Request, ValidationErr> {
check_bucket_name(&self.bucket, true)?; check_bucket_name(&self.bucket, true)?;
@ -74,10 +60,13 @@ impl ToS3Request for GetBucketLifecycle {
query_params.add("withUpdatedAt", "true"); query_params.add("withUpdatedAt", "true");
} }
Ok(S3Request::new(self.client, Method::GET) Ok(S3Request::builder()
.client(self.client)
.method(Method::GET)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.query_params(query_params) .query_params(query_params)
.headers(self.extra_headers.unwrap_or_default())) .headers(self.extra_headers.unwrap_or_default())
.build())
} }
} }

View File

@ -13,7 +13,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::builders::BucketCommon; use crate::s3::MinioClient;
use crate::s3::builders::{BucketCommon, BucketCommonBuilder};
use crate::s3::error::ValidationErr; use crate::s3::error::ValidationErr;
use crate::s3::response::GetBucketNotificationResponse; use crate::s3::response::GetBucketNotificationResponse;
use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::types::{S3Api, S3Request, ToS3Request};
@ -22,25 +23,36 @@ use http::Method;
/// Argument builder for the [`GetBucketNotification`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketNotification.html) S3 API operation. /// Argument builder for the [`GetBucketNotification`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketNotification.html) S3 API operation.
/// ///
/// This struct constructs the parameters required for the [`Client::get_bucket_notification`](crate::s3::client::Client::get_bucket_notification) method. /// This struct constructs the parameters required for the [`Client::get_bucket_notification`](crate::s3::client::MinioClient::get_bucket_notification) method.
pub type GetBucketNotification = BucketCommon<GetBucketNotificationPhantomData>; pub type GetBucketNotification = BucketCommon<GetBucketNotificationPhantomData>;
#[doc(hidden)] #[doc(hidden)]
#[derive(Default, Debug)] #[derive(Clone, Debug)]
pub struct GetBucketNotificationPhantomData; pub struct GetBucketNotificationPhantomData;
impl S3Api for GetBucketNotification { impl S3Api for GetBucketNotification {
type S3Response = GetBucketNotificationResponse; type S3Response = GetBucketNotificationResponse;
} }
/// Builder type for [`GetBucketNotification`] that is returned by [`MinioClient::get_bucket_notification`](crate::s3::client::MinioClient::get_bucket_notification).
///
/// This type alias simplifies the complex generic signature generated by the `typed_builder` crate.
pub type GetBucketNotificationBldr = BucketCommonBuilder<
GetBucketNotificationPhantomData,
((MinioClient,), (), (), (), (String,), ()),
>;
impl ToS3Request for GetBucketNotification { impl ToS3Request for GetBucketNotification {
fn to_s3request(self) -> Result<S3Request, ValidationErr> { fn to_s3request(self) -> Result<S3Request, ValidationErr> {
check_bucket_name(&self.bucket, true)?; check_bucket_name(&self.bucket, true)?;
Ok(S3Request::new(self.client, Method::GET) Ok(S3Request::builder()
.client(self.client)
.method(Method::GET)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.query_params(insert(self.extra_query_params, "notification")) .query_params(insert(self.extra_query_params, "notification"))
.headers(self.extra_headers.unwrap_or_default())) .headers(self.extra_headers.unwrap_or_default())
.build())
} }
} }

View File

@ -13,7 +13,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::builders::BucketCommon; use crate::s3::MinioClient;
use crate::s3::builders::{BucketCommon, BucketCommonBuilder};
use crate::s3::error::ValidationErr; use crate::s3::error::ValidationErr;
use crate::s3::response::GetBucketPolicyResponse; use crate::s3::response::GetBucketPolicyResponse;
use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::types::{S3Api, S3Request, ToS3Request};
@ -22,25 +23,34 @@ use http::Method;
/// Argument builder for the [`GetBucketPolicy`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketPolicy.html) S3 API operation. /// Argument builder for the [`GetBucketPolicy`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketPolicy.html) S3 API operation.
/// ///
/// This struct constructs the parameters required for the [`Client::get_bucket_policy`](crate::s3::client::Client::get_bucket_policy) method. /// This struct constructs the parameters required for the [`Client::get_bucket_policy`](crate::s3::client::MinioClient::get_bucket_policy) method.
pub type GetBucketPolicy = BucketCommon<GetBucketPolicyPhantomData>; pub type GetBucketPolicy = BucketCommon<GetBucketPolicyPhantomData>;
#[doc(hidden)] #[doc(hidden)]
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug)]
pub struct GetBucketPolicyPhantomData; pub struct GetBucketPolicyPhantomData;
impl S3Api for GetBucketPolicy { impl S3Api for GetBucketPolicy {
type S3Response = GetBucketPolicyResponse; type S3Response = GetBucketPolicyResponse;
} }
/// Builder type for [`GetBucketPolicy`] that is returned by [`MinioClient::get_bucket_policy`](crate::s3::client::MinioClient::get_bucket_policy).
///
/// This type alias simplifies the complex generic signature generated by the `typed_builder` crate.
pub type GetBucketPolicyBldr =
BucketCommonBuilder<GetBucketPolicyPhantomData, ((MinioClient,), (), (), (), (String,), ())>;
impl ToS3Request for GetBucketPolicy { impl ToS3Request for GetBucketPolicy {
fn to_s3request(self) -> Result<S3Request, ValidationErr> { fn to_s3request(self) -> Result<S3Request, ValidationErr> {
check_bucket_name(&self.bucket, true)?; check_bucket_name(&self.bucket, true)?;
Ok(S3Request::new(self.client, Method::GET) Ok(S3Request::builder()
.client(self.client)
.method(Method::GET)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.query_params(insert(self.extra_query_params, "policy")) .query_params(insert(self.extra_query_params, "policy"))
.headers(self.extra_headers.unwrap_or_default())) .headers(self.extra_headers.unwrap_or_default())
.build())
} }
} }

View File

@ -13,7 +13,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::builders::BucketCommon; use crate::s3::MinioClient;
use crate::s3::builders::{BucketCommon, BucketCommonBuilder};
use crate::s3::error::ValidationErr; use crate::s3::error::ValidationErr;
use crate::s3::response::GetBucketReplicationResponse; use crate::s3::response::GetBucketReplicationResponse;
use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::types::{S3Api, S3Request, ToS3Request};
@ -22,25 +23,36 @@ use http::Method;
/// Argument builder for the [`GetBucketReplication`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketReplication.html) S3 API operation. /// Argument builder for the [`GetBucketReplication`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketReplication.html) S3 API operation.
/// ///
/// This struct constructs the parameters required for the [`Client::get_bucket_replication`](crate::s3::client::Client::get_bucket_replication) method. /// This struct constructs the parameters required for the [`Client::get_bucket_replication`](crate::s3::client::MinioClient::get_bucket_replication) method.
pub type GetBucketReplication = BucketCommon<GetBucketReplicationPhantomData>; pub type GetBucketReplication = BucketCommon<GetBucketReplicationPhantomData>;
#[doc(hidden)] #[doc(hidden)]
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug)]
pub struct GetBucketReplicationPhantomData; pub struct GetBucketReplicationPhantomData;
impl S3Api for GetBucketReplication { impl S3Api for GetBucketReplication {
type S3Response = GetBucketReplicationResponse; type S3Response = GetBucketReplicationResponse;
} }
/// Builder type for [`GetBucketReplication`] that is returned by [`MinioClient::get_bucket_replication`](crate::s3::client::MinioClient::get_bucket_replication).
///
/// This type alias simplifies the complex generic signature generated by the `typed_builder` crate.
pub type GetBucketReplicationBldr = BucketCommonBuilder<
GetBucketReplicationPhantomData,
((MinioClient,), (), (), (), (String,), ()),
>;
impl ToS3Request for GetBucketReplication { impl ToS3Request for GetBucketReplication {
fn to_s3request(self) -> Result<S3Request, ValidationErr> { fn to_s3request(self) -> Result<S3Request, ValidationErr> {
check_bucket_name(&self.bucket, true)?; check_bucket_name(&self.bucket, true)?;
Ok(S3Request::new(self.client, Method::GET) Ok(S3Request::builder()
.client(self.client)
.method(Method::GET)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.query_params(insert(self.extra_query_params, "replication")) .query_params(insert(self.extra_query_params, "replication"))
.headers(self.extra_headers.unwrap_or_default())) .headers(self.extra_headers.unwrap_or_default())
.build())
} }
} }

View File

@ -13,73 +13,52 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::Client; use crate::s3::client::MinioClient;
use crate::s3::error::ValidationErr; use crate::s3::error::ValidationErr;
use crate::s3::multimap_ext::Multimap; use crate::s3::multimap_ext::Multimap;
use crate::s3::response::GetBucketTaggingResponse; use crate::s3::response::GetBucketTaggingResponse;
use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::types::{S3Api, S3Request, ToS3Request};
use crate::s3::utils::{check_bucket_name, insert}; use crate::s3::utils::{check_bucket_name, insert};
use http::Method; use http::Method;
use std::collections::HashMap; use typed_builder::TypedBuilder;
/// Argument builder for the [`GetBucketTagging`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketTagging.html) S3 API operation. /// Argument builder for the [`GetBucketTagging`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketTagging.html) S3 API operation.
/// ///
/// This struct constructs the parameters required for the [`Client::get_bucket_tagging`](crate::s3::client::Client::get_bucket_tagging) method. /// This struct constructs the parameters required for the [`Client::get_bucket_tagging`](crate::s3::client::MinioClient::get_bucket_tagging) method.
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, TypedBuilder)]
pub struct GetBucketTagging { pub struct GetBucketTagging {
client: Client, #[builder(!default)] // force required
client: MinioClient,
#[builder(default, setter(into))]
extra_headers: Option<Multimap>, extra_headers: Option<Multimap>,
#[builder(default, setter(into))]
extra_query_params: Option<Multimap>, extra_query_params: Option<Multimap>,
#[builder(default, setter(into))]
region: Option<String>, region: Option<String>,
#[builder(setter(into))] // force required + accept Into<String>
bucket: String, bucket: String,
tags: HashMap<String, String>,
}
impl GetBucketTagging {
pub fn new(client: Client, bucket: String) -> Self {
Self {
client,
bucket,
..Default::default()
}
}
pub fn extra_headers(mut self, extra_headers: Option<Multimap>) -> Self {
self.extra_headers = extra_headers;
self
}
pub fn extra_query_params(mut self, extra_query_params: Option<Multimap>) -> Self {
self.extra_query_params = extra_query_params;
self
}
/// Sets the region for the request
pub fn region(mut self, region: Option<String>) -> Self {
self.region = region;
self
}
pub fn tags(mut self, tags: HashMap<String, String>) -> Self {
self.tags = tags;
self
}
} }
impl S3Api for GetBucketTagging { impl S3Api for GetBucketTagging {
type S3Response = GetBucketTaggingResponse; type S3Response = GetBucketTaggingResponse;
} }
/// Builder type for [`GetBucketTagging`] that is returned by [`MinioClient::get_bucket_tagging`](crate::s3::client::MinioClient::get_bucket_tagging).
///
/// This type alias simplifies the complex generic signature generated by the `typed_builder` crate.
pub type GetBucketTaggingBldr = GetBucketTaggingBuilder<((MinioClient,), (), (), (), (String,))>;
impl ToS3Request for GetBucketTagging { impl ToS3Request for GetBucketTagging {
fn to_s3request(self) -> Result<S3Request, ValidationErr> { fn to_s3request(self) -> Result<S3Request, ValidationErr> {
check_bucket_name(&self.bucket, true)?; check_bucket_name(&self.bucket, true)?;
Ok(S3Request::new(self.client, Method::GET) Ok(S3Request::builder()
.client(self.client)
.method(Method::GET)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.query_params(insert(self.extra_query_params, "tagging")) .query_params(insert(self.extra_query_params, "tagging"))
.headers(self.extra_headers.unwrap_or_default())) .headers(self.extra_headers.unwrap_or_default())
.build())
} }
} }

View File

@ -13,7 +13,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::builders::BucketCommon; use crate::s3::MinioClient;
use crate::s3::builders::{BucketCommon, BucketCommonBuilder};
use crate::s3::error::ValidationErr; use crate::s3::error::ValidationErr;
use crate::s3::response::GetBucketVersioningResponse; use crate::s3::response::GetBucketVersioningResponse;
use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::types::{S3Api, S3Request, ToS3Request};
@ -22,25 +23,36 @@ use http::Method;
/// Argument builder for the [`GetBucketVersioning`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketVersioning.html) S3 API operation. /// Argument builder for the [`GetBucketVersioning`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketVersioning.html) S3 API operation.
/// ///
/// This struct constructs the parameters required for the [`Client::get_bucket_versioning`](crate::s3::client::Client::get_bucket_versioning) method. /// This struct constructs the parameters required for the [`Client::get_bucket_versioning`](crate::s3::client::MinioClient::get_bucket_versioning) method.
pub type GetBucketVersioning = BucketCommon<GetBucketVersioningPhantomData>; pub type GetBucketVersioning = BucketCommon<GetBucketVersioningPhantomData>;
#[doc(hidden)] #[doc(hidden)]
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug)]
pub struct GetBucketVersioningPhantomData; pub struct GetBucketVersioningPhantomData;
impl S3Api for GetBucketVersioning { impl S3Api for GetBucketVersioning {
type S3Response = GetBucketVersioningResponse; type S3Response = GetBucketVersioningResponse;
} }
/// Builder type for [`GetBucketVersioning`] that is returned by [`MinioClient::get_bucket_versioning`](crate::s3::client::MinioClient::get_bucket_versioning).
///
/// This type alias simplifies the complex generic signature generated by the `typed_builder` crate.
pub type GetBucketVersioningBldr = BucketCommonBuilder<
GetBucketVersioningPhantomData,
((MinioClient,), (), (), (), (String,), ()),
>;
impl ToS3Request for GetBucketVersioning { impl ToS3Request for GetBucketVersioning {
fn to_s3request(self) -> Result<S3Request, ValidationErr> { fn to_s3request(self) -> Result<S3Request, ValidationErr> {
check_bucket_name(&self.bucket, true)?; check_bucket_name(&self.bucket, true)?;
Ok(S3Request::new(self.client, Method::GET) Ok(S3Request::builder()
.client(self.client)
.method(Method::GET)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.query_params(insert(self.extra_query_params, "versioning")) .query_params(insert(self.extra_query_params, "versioning"))
.headers(self.extra_headers.unwrap_or_default())) .headers(self.extra_headers.unwrap_or_default())
.build())
} }
} }

View File

@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::client::Client; use crate::s3::client::MinioClient;
use crate::s3::error::ValidationErr; use crate::s3::error::ValidationErr;
use crate::s3::header_constants::*; use crate::s3::header_constants::*;
use crate::s3::multimap_ext::{Multimap, MultimapExt}; use crate::s3::multimap_ext::{Multimap, MultimapExt};
@ -24,97 +24,64 @@ use crate::s3::utils::{
UtcTime, check_bucket_name, check_object_name, check_ssec, to_http_header_value, UtcTime, check_bucket_name, check_object_name, check_ssec, to_http_header_value,
}; };
use http::Method; use http::Method;
use typed_builder::TypedBuilder;
/// Argument builder for the [`GetObject`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html) S3 API operation. /// Argument builder for the [`GetObject`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html) S3 API operation.
/// ///
/// This struct constructs the parameters required for the [`Client::get_object`](crate::s3::client::Client::get_object) method. /// This struct constructs the parameters required for the [`Client::get_object`](crate::s3::client::MinioClient::get_object) method.
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, TypedBuilder)]
pub struct GetObject { pub struct GetObject {
client: Client, #[builder(!default)] // force required
client: MinioClient,
#[builder(default, setter(into))]
extra_headers: Option<Multimap>, extra_headers: Option<Multimap>,
#[builder(default, setter(into))]
extra_query_params: Option<Multimap>, extra_query_params: Option<Multimap>,
bucket: String, #[builder(default, setter(into))]
object: String,
version_id: Option<String>,
offset: Option<u64>,
length: Option<u64>,
region: Option<String>, region: Option<String>,
#[builder(setter(into))] // force required + accept Into<String>
bucket: String,
#[builder(setter(into))] // force required + accept Into<String>
object: String,
#[builder(default, setter(into))]
version_id: Option<String>,
#[builder(default, setter(into))]
offset: Option<u64>,
#[builder(default, setter(into))]
length: Option<u64>,
#[builder(default, setter(into))]
ssec: Option<SseCustomerKey>, ssec: Option<SseCustomerKey>,
// Conditionals // Conditionals
#[builder(default, setter(into))]
match_etag: Option<String>, match_etag: Option<String>,
#[builder(default, setter(into))]
not_match_etag: Option<String>, not_match_etag: Option<String>,
#[builder(default, setter(into))]
modified_since: Option<UtcTime>, modified_since: Option<UtcTime>,
#[builder(default, setter(into))]
unmodified_since: Option<UtcTime>, unmodified_since: Option<UtcTime>,
} }
impl GetObject { /// Builder type alias for [`GetObject`].
pub fn new(client: Client, bucket: String, object: String) -> Self { ///
Self { /// Constructed via [`GetObject::builder()`](GetObject::builder) and used to build a [`GetObject`] instance.
client, pub type GetObjectBldr = GetObjectBuilder<(
bucket, (MinioClient,),
object, (),
..Default::default() (),
} (),
} (String,),
(String,),
pub fn extra_headers(mut self, extra_headers: Option<Multimap>) -> Self { (),
self.extra_headers = extra_headers; (),
self (),
} (),
(),
pub fn extra_query_params(mut self, extra_query_params: Option<Multimap>) -> Self { (),
self.extra_query_params = extra_query_params; (),
self (),
} )>;
pub fn version_id(mut self, version_id: Option<String>) -> Self {
self.version_id = version_id;
self
}
pub fn offset(mut self, offset: Option<u64>) -> Self {
self.offset = offset;
self
}
pub fn length(mut self, length: Option<u64>) -> Self {
self.length = length;
self
}
/// Sets the region for the request
pub fn region(mut self, region: Option<String>) -> Self {
self.region = region;
self
}
pub fn ssec(mut self, ssec: Option<SseCustomerKey>) -> Self {
self.ssec = ssec;
self
}
pub fn match_etag(mut self, etag: Option<String>) -> Self {
self.match_etag = etag;
self
}
pub fn not_match_etag(mut self, etag: Option<String>) -> Self {
self.not_match_etag = etag;
self
}
pub fn modified_since(mut self, time: Option<UtcTime>) -> Self {
self.modified_since = time;
self
}
pub fn unmodified_since(mut self, time: Option<UtcTime>) -> Self {
self.unmodified_since = time;
self
}
}
impl S3Api for GetObject { impl S3Api for GetObject {
type S3Response = GetObjectResponse; type S3Response = GetObjectResponse;
@ -170,11 +137,14 @@ impl ToS3Request for GetObject {
let mut query_params: Multimap = self.extra_query_params.unwrap_or_default(); let mut query_params: Multimap = self.extra_query_params.unwrap_or_default();
query_params.add_version(self.version_id); query_params.add_version(self.version_id);
Ok(S3Request::new(self.client, Method::GET) Ok(S3Request::builder()
.client(self.client)
.method(Method::GET)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.object(Some(self.object)) .object(self.object)
.query_params(query_params) .query_params(query_params)
.headers(headers)) .headers(headers)
.build())
} }
} }

View File

@ -13,55 +13,38 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::Client; use crate::s3::client::MinioClient;
use crate::s3::error::ValidationErr; use crate::s3::error::ValidationErr;
use crate::s3::multimap_ext::{Multimap, MultimapExt}; use crate::s3::multimap_ext::{Multimap, MultimapExt};
use crate::s3::response::GetObjectLegalHoldResponse; use crate::s3::response::GetObjectLegalHoldResponse;
use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::types::{S3Api, S3Request, ToS3Request};
use crate::s3::utils::{check_bucket_name, check_object_name, insert}; use crate::s3::utils::{check_bucket_name, check_object_name, insert};
use http::Method; use http::Method;
use typed_builder::TypedBuilder;
/// Argument builder for the [`GetObjectLegalHold`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectLegalHold.html) S3 API operation. /// Argument builder for the [`GetObjectLegalHold`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectLegalHold.html) S3 API operation.
/// ///
/// This struct constructs the parameters required for the [`Client::get_object_legal_hold`](crate::s3::client::Client::get_object_legal_hold) method. /// This struct constructs the parameters required for the [`Client::get_object_legal_hold`](crate::s3::client::MinioClient::get_object_legal_hold) method.
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, TypedBuilder)]
pub struct GetObjectLegalHold { pub struct GetObjectLegalHold {
client: Client, #[builder(!default)] // force required
client: MinioClient,
#[builder(default, setter(into))]
extra_headers: Option<Multimap>, extra_headers: Option<Multimap>,
#[builder(default, setter(into))]
extra_query_params: Option<Multimap>, extra_query_params: Option<Multimap>,
#[builder(default, setter(into))]
region: Option<String>, region: Option<String>,
#[builder(setter(into))] // force required + accept Into<String>
bucket: String, bucket: String,
#[builder(setter(into))] // force required + accept Into<String>
object: String, object: String,
#[builder(default, setter(into))]
version_id: Option<String>, version_id: Option<String>,
} }
impl GetObjectLegalHold { pub type GetObjectLegalHoldBldr =
pub fn new(client: Client, bucket: String, object: String) -> Self { GetObjectLegalHoldBuilder<((MinioClient,), (), (), (), (String,), (String,), ())>;
Self {
client,
bucket,
object,
..Default::default()
}
}
pub fn extra_headers(mut self, extra_headers: Option<Multimap>) -> Self {
self.extra_headers = extra_headers;
self
}
pub fn extra_query_params(mut self, extra_query_params: Option<Multimap>) -> Self {
self.extra_query_params = extra_query_params;
self
}
pub fn version_id(mut self, version_id: Option<String>) -> Self {
self.version_id = version_id;
self
}
}
impl S3Api for GetObjectLegalHold { impl S3Api for GetObjectLegalHold {
type S3Response = GetObjectLegalHoldResponse; type S3Response = GetObjectLegalHoldResponse;
@ -75,11 +58,14 @@ impl ToS3Request for GetObjectLegalHold {
let mut query_params: Multimap = insert(self.extra_query_params, "legal-hold"); let mut query_params: Multimap = insert(self.extra_query_params, "legal-hold");
query_params.add_version(self.version_id); query_params.add_version(self.version_id);
Ok(S3Request::new(self.client, Method::GET) Ok(S3Request::builder()
.client(self.client)
.method(Method::GET)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.query_params(query_params) .query_params(query_params)
.headers(self.extra_headers.unwrap_or_default()) .headers(self.extra_headers.unwrap_or_default())
.object(Some(self.object))) .object(self.object)
.build())
} }
} }

View File

@ -13,7 +13,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::builders::BucketCommon; use crate::s3::MinioClient;
use crate::s3::builders::{BucketCommon, BucketCommonBuilder};
use crate::s3::error::ValidationErr; use crate::s3::error::ValidationErr;
use crate::s3::response::GetObjectLockConfigResponse; use crate::s3::response::GetObjectLockConfigResponse;
use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::types::{S3Api, S3Request, ToS3Request};
@ -22,13 +23,18 @@ use http::Method;
/// Argument builder for the [`GetObjectLockConfig`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectLockConfiguration.html) S3 API operation. /// Argument builder for the [`GetObjectLockConfig`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectLockConfiguration.html) S3 API operation.
/// ///
/// This struct constructs the parameters required for the [`Client::get_object_lock_config`](crate::s3::client::Client::get_object_lock_config) method. /// This struct constructs the parameters required for the [`Client::get_object_lock_config`](crate::s3::client::MinioClient::get_object_lock_config) method.
pub type GetObjectLockConfig = BucketCommon<GetObjectLockConfigPhantomData>; pub type GetObjectLockConfig = BucketCommon<GetObjectLockConfigPhantomData>;
#[doc(hidden)] #[doc(hidden)]
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug)]
pub struct GetObjectLockConfigPhantomData; pub struct GetObjectLockConfigPhantomData;
pub type GetObjectLockConfigBldr = BucketCommonBuilder<
GetObjectLockConfigPhantomData,
((MinioClient,), (), (), (), (String,), ()),
>;
impl S3Api for GetObjectLockConfig { impl S3Api for GetObjectLockConfig {
type S3Response = GetObjectLockConfigResponse; type S3Response = GetObjectLockConfigResponse;
} }
@ -37,10 +43,13 @@ impl ToS3Request for GetObjectLockConfig {
fn to_s3request(self) -> Result<S3Request, ValidationErr> { fn to_s3request(self) -> Result<S3Request, ValidationErr> {
check_bucket_name(&self.bucket, true)?; check_bucket_name(&self.bucket, true)?;
Ok(S3Request::new(self.client, Method::GET) Ok(S3Request::builder()
.client(self.client)
.method(Method::GET)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.query_params(insert(self.extra_query_params, "object-lock")) .query_params(insert(self.extra_query_params, "object-lock"))
.headers(self.extra_headers.unwrap_or_default())) .headers(self.extra_headers.unwrap_or_default())
.build())
} }
} }

View File

@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::client::Client; use crate::s3::client::MinioClient;
use crate::s3::error::ValidationErr; use crate::s3::error::ValidationErr;
use crate::s3::multimap_ext::{Multimap, MultimapExt}; use crate::s3::multimap_ext::{Multimap, MultimapExt};
use crate::s3::response::GetObjectPromptResponse; use crate::s3::response::GetObjectPromptResponse;
@ -24,68 +24,48 @@ use crate::s3::utils::{check_bucket_name, check_object_name, check_ssec};
use bytes::Bytes; use bytes::Bytes;
use http::Method; use http::Method;
use serde_json::json; use serde_json::json;
use std::sync::Arc;
use typed_builder::TypedBuilder;
/// Argument builder for the `GetObjectPrompt` operation. /// Argument builder for the `GetObjectPrompt` operation.
/// ///
/// This struct constructs the parameters required for the [`Client::get_object_prompt`](crate::s3::client::Client::get_object_prompt) method. /// This struct constructs the parameters required for the [`Client::get_object_prompt`](crate::s3::client::MinioClient::get_object_prompt) method.
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, TypedBuilder)]
pub struct GetObjectPrompt { pub struct GetObjectPrompt {
client: Client, #[builder(!default)] // force required
bucket: String, client: MinioClient,
object: String, #[builder(default, setter(into))]
prompt: String,
lambda_arn: Option<String>,
version_id: Option<String>,
region: Option<String>,
ssec: Option<SseCustomerKey>,
extra_headers: Option<Multimap>, extra_headers: Option<Multimap>,
#[builder(default, setter(into))]
extra_query_params: Option<Multimap>, extra_query_params: Option<Multimap>,
#[builder(default, setter(into))]
region: Option<String>,
#[builder(setter(into))] // force required + accept Into<String>
bucket: String,
#[builder(setter(into))] // force required + accept Into<String>
object: String,
#[builder(setter(into))] // force required + accept Into<String>
prompt: String,
#[builder(default, setter(into))]
lambda_arn: Option<String>,
#[builder(default, setter(into))]
version_id: Option<String>,
#[builder(default, setter(into))]
ssec: Option<SseCustomerKey>,
} }
// builder interface pub type GetObjectPromptBldr = GetObjectPromptBuilder<(
impl GetObjectPrompt { (MinioClient,),
pub fn new(client: Client, bucket: String, object: String, prompt: String) -> Self { (),
GetObjectPrompt { (),
client, (),
bucket, (String,),
object, (String,),
prompt, (String,),
..Default::default() (),
} (),
} (),
)>;
pub fn lambda_arn(mut self, lambda_arn: &str) -> Self {
self.lambda_arn = Some(lambda_arn.to_string());
self
}
pub fn extra_headers(mut self, extra_headers: Option<Multimap>) -> Self {
self.extra_headers = extra_headers;
self
}
pub fn extra_query_params(mut self, extra_query_params: Option<Multimap>) -> Self {
self.extra_query_params = extra_query_params;
self
}
pub fn version_id(mut self, version_id: Option<String>) -> Self {
self.version_id = version_id;
self
}
/// Sets the region for the request
pub fn region(mut self, region: Option<String>) -> Self {
self.region = region;
self
}
pub fn ssec(mut self, ssec: Option<SseCustomerKey>) -> Self {
self.ssec = ssec;
self
}
}
impl S3Api for GetObjectPrompt { impl S3Api for GetObjectPrompt {
type S3Response = GetObjectPromptResponse; type S3Response = GetObjectPromptResponse;
@ -113,14 +93,17 @@ impl ToS3Request for GetObjectPrompt {
); );
let prompt_body = json!({ "prompt": self.prompt }); let prompt_body = json!({ "prompt": self.prompt });
let body: SegmentedBytes = SegmentedBytes::from(Bytes::from(prompt_body.to_string())); let body = Arc::new(SegmentedBytes::from(Bytes::from(prompt_body.to_string())));
Ok(S3Request::new(self.client, Method::POST) Ok(S3Request::builder()
.client(self.client)
.method(Method::POST)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.object(Some(self.object)) .object(self.object)
.query_params(query_params) .query_params(query_params)
.headers(self.extra_headers.unwrap_or_default()) .headers(self.extra_headers.unwrap_or_default())
.body(Some(body))) .body(body)
.build())
} }
} }

View File

@ -13,61 +13,41 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::Client; use crate::s3::client::MinioClient;
use crate::s3::error::ValidationErr; use crate::s3::error::ValidationErr;
use crate::s3::multimap_ext::{Multimap, MultimapExt}; use crate::s3::multimap_ext::{Multimap, MultimapExt};
use crate::s3::response::GetObjectRetentionResponse; use crate::s3::response::GetObjectRetentionResponse;
use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::types::{S3Api, S3Request, ToS3Request};
use crate::s3::utils::{check_bucket_name, check_object_name, insert}; use crate::s3::utils::{check_bucket_name, check_object_name, insert};
use http::Method; use http::Method;
use typed_builder::TypedBuilder;
/// Argument builder for the [`GetObjectRetention`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectRetention.html) S3 API operation. /// Argument builder for the [`GetObjectRetention`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectRetention.html) S3 API operation.
/// ///
/// This struct constructs the parameters required for the [`Client::get_object_retention`](crate::s3::client::Client::get_object_retention) method. /// This struct constructs the parameters required for the [`Client::get_object_retention`](crate::s3::client::MinioClient::get_object_retention) method.
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, TypedBuilder)]
pub struct GetObjectRetention { pub struct GetObjectRetention {
client: Client, #[builder(!default)] // force required
client: MinioClient,
#[builder(default, setter(into))]
extra_headers: Option<Multimap>, extra_headers: Option<Multimap>,
#[builder(default, setter(into))]
extra_query_params: Option<Multimap>, extra_query_params: Option<Multimap>,
#[builder(default, setter(into))]
region: Option<String>, region: Option<String>,
#[builder(setter(into))] // force required + accept Into<String>
bucket: String, bucket: String,
#[builder(setter(into))] // force required + accept Into<String>
object: String, object: String,
#[builder(default, setter(into))]
version_id: Option<String>, version_id: Option<String>,
} }
impl GetObjectRetention { /// Builder type alias for [`GetObjectRetention`].
pub fn new(client: Client, bucket: String, object: String) -> Self { ///
Self { /// Constructed via [`GetObjectRetention::builder()`](GetObjectRetention::builder) and used to build a [`GetObjectRetention`] instance.
client, pub type GetObjectRetentionBldr =
bucket, GetObjectRetentionBuilder<((MinioClient,), (), (), (), (String,), (String,), ())>;
object,
..Default::default()
}
}
pub fn extra_headers(mut self, extra_headers: Option<Multimap>) -> Self {
self.extra_headers = extra_headers;
self
}
pub fn extra_query_params(mut self, extra_query_params: Option<Multimap>) -> Self {
self.extra_query_params = extra_query_params;
self
}
/// Sets the region for the request
pub fn region(mut self, region: Option<String>) -> Self {
self.region = region;
self
}
pub fn version_id(mut self, version_id: Option<String>) -> Self {
self.version_id = version_id;
self
}
}
impl S3Api for GetObjectRetention { impl S3Api for GetObjectRetention {
type S3Response = GetObjectRetentionResponse; type S3Response = GetObjectRetentionResponse;
@ -81,11 +61,14 @@ impl ToS3Request for GetObjectRetention {
let mut query_params: Multimap = insert(self.extra_query_params, "retention"); let mut query_params: Multimap = insert(self.extra_query_params, "retention");
query_params.add_version(self.version_id); query_params.add_version(self.version_id);
Ok(S3Request::new(self.client, Method::GET) Ok(S3Request::builder()
.client(self.client)
.method(Method::GET)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.query_params(query_params) .query_params(query_params)
.object(Some(self.object)) .object(self.object)
.headers(self.extra_headers.unwrap_or_default())) .headers(self.extra_headers.unwrap_or_default())
.build())
} }
} }

View File

@ -13,61 +13,38 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::Client; use crate::s3::client::MinioClient;
use crate::s3::error::ValidationErr; use crate::s3::error::ValidationErr;
use crate::s3::multimap_ext::{Multimap, MultimapExt}; use crate::s3::multimap_ext::{Multimap, MultimapExt};
use crate::s3::response::GetObjectTaggingResponse; use crate::s3::response::GetObjectTaggingResponse;
use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::types::{S3Api, S3Request, ToS3Request};
use crate::s3::utils::{check_bucket_name, check_object_name, insert}; use crate::s3::utils::{check_bucket_name, check_object_name, insert};
use http::Method; use http::Method;
use typed_builder::TypedBuilder;
/// Argument builder for the [`GetObjectTagging`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectTagging.html) S3 API operation. /// Argument builder for the [`GetObjectTagging`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectTagging.html) S3 API operation.
/// ///
/// This struct constructs the parameters required for the [`Client::get_object_tagging`](crate::s3::client::Client::get_object_tagging) method. /// This struct constructs the parameters required for the [`Client::get_object_tagging`](crate::s3::client::MinioClient::get_object_tagging) method.
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, TypedBuilder)]
pub struct GetObjectTagging { pub struct GetObjectTagging {
client: Client, #[builder(!default)] // force required
client: MinioClient,
#[builder(default, setter(into))]
extra_headers: Option<Multimap>, extra_headers: Option<Multimap>,
#[builder(default, setter(into))]
extra_query_params: Option<Multimap>, extra_query_params: Option<Multimap>,
#[builder(default, setter(into))]
region: Option<String>, region: Option<String>,
#[builder(setter(into))] // force required + accept Into<String>
bucket: String, bucket: String,
#[builder(setter(into))] // force required + accept Into<String>
object: String, object: String,
#[builder(default, setter(into))]
version_id: Option<String>, version_id: Option<String>,
} }
impl GetObjectTagging { pub type GetObjectTaggingBldr =
pub fn new(client: Client, bucket: String, object: String) -> Self { GetObjectTaggingBuilder<((MinioClient,), (), (), (), (String,), (String,), ())>;
Self {
client,
bucket,
object,
..Default::default()
}
}
pub fn extra_headers(mut self, extra_headers: Option<Multimap>) -> Self {
self.extra_headers = extra_headers;
self
}
pub fn extra_query_params(mut self, extra_query_params: Option<Multimap>) -> Self {
self.extra_query_params = extra_query_params;
self
}
/// Sets the region for the request
pub fn region(mut self, region: Option<String>) -> Self {
self.region = region;
self
}
pub fn version_id(mut self, version_id: Option<String>) -> Self {
self.version_id = version_id;
self
}
}
impl S3Api for GetObjectTagging { impl S3Api for GetObjectTagging {
type S3Response = GetObjectTaggingResponse; type S3Response = GetObjectTaggingResponse;
@ -81,11 +58,14 @@ impl ToS3Request for GetObjectTagging {
let mut query_params: Multimap = insert(self.extra_query_params, "tagging"); let mut query_params: Multimap = insert(self.extra_query_params, "tagging");
query_params.add_version(self.version_id); query_params.add_version(self.version_id);
Ok(S3Request::new(self.client, Method::GET) Ok(S3Request::builder()
.client(self.client)
.method(Method::GET)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.query_params(query_params) .query_params(query_params)
.object(Some(self.object)) .object(self.object)
.headers(self.extra_headers.unwrap_or_default())) .headers(self.extra_headers.unwrap_or_default())
.build())
} }
} }

View File

@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::Client; use crate::s3::client::MinioClient;
use crate::s3::creds::Credentials; use crate::s3::creds::Credentials;
use crate::s3::error::Error; use crate::s3::error::Error;
use crate::s3::header_constants::*; use crate::s3::header_constants::*;
@ -22,51 +22,51 @@ use crate::s3::response::GetPresignedObjectUrlResponse;
use crate::s3::signer::presign_v4; use crate::s3::signer::presign_v4;
use crate::s3::utils::{UtcTime, check_bucket_name, check_object_name, utc_now}; use crate::s3::utils::{UtcTime, check_bucket_name, check_object_name, utc_now};
use http::Method; use http::Method;
use typed_builder::TypedBuilder;
/// The default expiry time in seconds for a [`GetPresignedObjectUrl`]. /// The default expiry time in seconds for a [`GetPresignedObjectUrl`].
pub const DEFAULT_EXPIRY_SECONDS: u32 = 604_800; // 7 days pub const DEFAULT_EXPIRY_SECONDS: u32 = 604_800; // 7 days
/// This struct constructs the parameters required for the [`Client::get_presigned_object_url`](crate::s3::client::Client::get_presigned_object_url) method. /// This struct constructs the parameters required for the [`Client::get_presigned_object_url`](crate::s3::client::MinioClient::get_presigned_object_url) method.
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, TypedBuilder)]
pub struct GetPresignedObjectUrl { pub struct GetPresignedObjectUrl {
client: Client, #[builder(!default)] // force required
client: MinioClient,
#[builder(default, setter(into))]
extra_query_params: Option<Multimap>, extra_query_params: Option<Multimap>,
#[builder(default, setter(into))]
region: Option<String>, region: Option<String>,
#[builder(setter(into))] // force required + accept Into<String>
bucket: String, bucket: String,
#[builder(setter(into))] // force required + accept Into<String>
object: String, object: String,
#[builder(default, setter(into))]
version_id: Option<String>, version_id: Option<String>,
#[builder(!default)]
method: Method, method: Method,
#[builder(default=Some(DEFAULT_EXPIRY_SECONDS), setter(into))]
expiry_seconds: Option<u32>, expiry_seconds: Option<u32>,
#[builder(default, setter(into))]
request_time: Option<UtcTime>, request_time: Option<UtcTime>,
} }
/// Builder type alias for [`GetPresignedObjectUrl`].
///
/// Constructed via [`GetPresignedObjectUrl::builder()`](GetPresignedObjectUrl::builder) and used to build a [`GetPresignedObjectUrl`] instance.
pub type GetPresignedObjectUrlBldr = GetPresignedObjectUrlBuilder<(
(MinioClient,),
(),
(),
(String,),
(String,),
(),
(Method,),
(),
(),
)>;
impl GetPresignedObjectUrl { impl GetPresignedObjectUrl {
pub fn new(client: Client, bucket: String, object: String, method: Method) -> Self {
Self {
client,
bucket,
object,
method,
expiry_seconds: Some(DEFAULT_EXPIRY_SECONDS),
..Default::default()
}
}
/// Sets the expiry time for the presigned URL, defaulting to 7 days if not specified.
pub fn expiry_seconds(mut self, seconds: u32) -> Self {
self.expiry_seconds = Some(seconds);
self
}
/// Sets the request time for the presigned URL, defaulting to the current time if not specified.
pub fn request_time(mut self, time: UtcTime) -> Self {
self.request_time = Some(time);
self
}
/// Sends the request to generate a presigned URL for an S3 object. /// Sends the request to generate a presigned URL for an S3 object.
pub async fn send(self) -> Result<GetPresignedObjectUrlResponse, Error> { pub async fn send(self) -> Result<GetPresignedObjectUrlResponse, Error> {
check_bucket_name(&self.bucket, true)?; check_bucket_name(&self.bucket, true)?;

View File

@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::Client; use crate::s3::client::MinioClient;
use crate::s3::creds::Credentials; use crate::s3::creds::Credentials;
use crate::s3::error::{Error, ValidationErr}; use crate::s3::error::{Error, ValidationErr};
use crate::s3::header_constants::*; use crate::s3::header_constants::*;
@ -23,18 +23,20 @@ use crate::s3::utils::{
}; };
use serde_json::{Value, json}; use serde_json::{Value, json};
use std::collections::HashMap; use std::collections::HashMap;
use typed_builder::TypedBuilder;
/// This struct constructs the parameters required for the [`Client::get_presigned_object_url`](crate::s3::client::Client::get_presigned_object_url) method. /// Argument builder for generating presigned POST policy for the [`POST Object`](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html) S3 API operation.
///
/// This struct constructs the parameters required for the [`Client::get_presigned_policy_form_data`](crate::s3::client::Client::get_presigned_policy_form_data) method.
#[derive(Debug, Clone, TypedBuilder)]
pub struct GetPresignedPolicyFormData { pub struct GetPresignedPolicyFormData {
client: Client, #[builder(!default)] // force required
client: MinioClient,
#[builder(!default)] // force required
policy: PostPolicy, policy: PostPolicy,
} }
impl GetPresignedPolicyFormData { impl GetPresignedPolicyFormData {
pub fn new(client: Client, policy: PostPolicy) -> Self {
Self { client, policy }
}
pub async fn send(self) -> Result<HashMap<String, String>, Error> { pub async fn send(self) -> Result<HashMap<String, String>, Error> {
let region: String = self let region: String = self
.client .client
@ -53,11 +55,17 @@ impl GetPresignedPolicyFormData {
} }
} }
/// Builder type alias for [`GetPresignedPolicyFormData`].
///
/// Constructed via [`GetPresignedPolicyFormData::builder()`](GetPresignedPolicyFormData::builder) and used to build a [`GetPresignedPolicyFormData`] instance.
pub type GetPresignedPolicyFormDataBldr =
GetPresignedPolicyFormDataBuilder<((MinioClient,), (PostPolicy,))>;
/// Post policy information for presigned post policy form-data /// Post policy information for presigned post policy form-data
/// ///
/// Condition elements and respective condition for Post policy is available <a /// Condition elements and respective condition for Post policy is available <a
/// href="https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-HTTPPOSTConstructPolicy.html#sigv4-PolicyConditions">here</a>. /// href="https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-HTTPPOSTConstructPolicy.html#sigv4-PolicyConditions">here</a>.
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug)]
pub struct PostPolicy { pub struct PostPolicy {
pub region: Option<String>, pub region: Option<String>,
pub bucket: String, pub bucket: String,
@ -89,9 +97,13 @@ impl PostPolicy {
check_bucket_name(bucket_name, true)?; check_bucket_name(bucket_name, true)?;
Ok(Self { Ok(Self {
region: None,
bucket: bucket_name.to_owned(), bucket: bucket_name.to_owned(),
expiration, expiration,
..Default::default() eq_conditions: Default::default(),
starts_with_conditions: Default::default(),
lower_limit: None,
upper_limit: None,
}) })
} }

View File

@ -13,46 +13,35 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::Client;
use crate::s3::client::DEFAULT_REGION; use crate::s3::client::DEFAULT_REGION;
use crate::s3::client::MinioClient;
use crate::s3::error::ValidationErr; use crate::s3::error::ValidationErr;
use crate::s3::multimap_ext::Multimap; use crate::s3::multimap_ext::Multimap;
use crate::s3::response::GetRegionResponse; use crate::s3::response::GetRegionResponse;
use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::types::{S3Api, S3Request, ToS3Request};
use crate::s3::utils::{check_bucket_name, insert}; use crate::s3::utils::{check_bucket_name, insert};
use http::Method; use http::Method;
use typed_builder::TypedBuilder;
/// Argument builder for the [`GetRegion`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadBucket.html) S3 API operation. /// Argument builder for the [`GetRegion`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadBucket.html) S3 API operation.
/// ///
/// This struct constructs the parameters required for the [`Client::get_region`](crate::s3::client::Client::get_region) method. /// This struct constructs the parameters required for the [`Client::get_region`](crate::s3::client::MinioClient::get_region) method.
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, TypedBuilder)]
pub struct GetRegion { pub struct GetRegion {
client: Client, #[builder(!default)] // force required
client: MinioClient,
#[builder(default, setter(into))]
extra_headers: Option<Multimap>, extra_headers: Option<Multimap>,
#[builder(default, setter(into))]
extra_query_params: Option<Multimap>, extra_query_params: Option<Multimap>,
#[builder(setter(into))] // force required + accept Into<String>
bucket: String, bucket: String,
} }
impl GetRegion { /// Builder type alias for [`GetRegion`].
pub fn new(client: Client, bucket: String) -> Self { ///
Self { /// Constructed via [`GetRegion::builder()`](GetRegion::builder) and used to build a [`GetRegion`] instance.
client, pub type GetRegionBldr = GetRegionBuilder<((MinioClient,), (), (), (String,))>;
bucket,
..Default::default()
}
}
pub fn extra_headers(mut self, extra_headers: Option<Multimap>) -> Self {
self.extra_headers = extra_headers;
self
}
pub fn extra_query_params(mut self, extra_query_params: Option<Multimap>) -> Self {
self.extra_query_params = extra_query_params;
self
}
}
#[doc(hidden)] #[doc(hidden)]
#[derive(Default, Debug)] #[derive(Default, Debug)]
@ -66,10 +55,13 @@ impl ToS3Request for GetRegion {
fn to_s3request(self) -> Result<S3Request, ValidationErr> { fn to_s3request(self) -> Result<S3Request, ValidationErr> {
check_bucket_name(&self.bucket, true)?; check_bucket_name(&self.bucket, true)?;
Ok(S3Request::new(self.client, Method::GET) Ok(S3Request::builder()
.region(Some(DEFAULT_REGION.to_string())) .client(self.client)
.bucket(Some(self.bucket)) .method(Method::GET)
.region(DEFAULT_REGION.to_string())
.bucket(self.bucket)
.query_params(insert(self.extra_query_params, "location")) .query_params(insert(self.extra_query_params, "location"))
.headers(self.extra_headers.unwrap_or_default())) .headers(self.extra_headers.unwrap_or_default())
.build())
} }
} }

View File

@ -13,42 +13,31 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::Client; use crate::s3::client::MinioClient;
use crate::s3::error::ValidationErr; use crate::s3::error::ValidationErr;
use crate::s3::multimap_ext::Multimap; use crate::s3::multimap_ext::Multimap;
use crate::s3::response::ListBucketsResponse; use crate::s3::response::ListBucketsResponse;
use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::types::{S3Api, S3Request, ToS3Request};
use http::Method; use http::Method;
use typed_builder::TypedBuilder;
/// Argument builder for the [`ListBuckets`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListBuckets.html) S3 API operation. /// Argument builder for the [`ListBuckets`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListBuckets.html) S3 API operation.
/// ///
/// This struct constructs the parameters required for the [`Client::list_buckets`](crate::s3::client::Client::list_buckets) method. /// This struct constructs the parameters required for the [`Client::list_buckets`](crate::s3::client::MinioClient::list_buckets) method.
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, TypedBuilder)]
pub struct ListBuckets { pub struct ListBuckets {
client: Client, #[builder(!default)] // force required
client: MinioClient,
#[builder(default, setter(into))]
extra_headers: Option<Multimap>, extra_headers: Option<Multimap>,
#[builder(default, setter(into))]
extra_query_params: Option<Multimap>, extra_query_params: Option<Multimap>,
} }
impl ListBuckets { /// Builder type alias for [`ListBuckets`].
pub fn new(client: Client) -> Self { ///
Self { /// Constructed via [`ListBuckets::builder()`](ListBuckets::builder) and used to build a [`ListBuckets`] instance.
client, pub type ListBucketsBldr = ListBucketsBuilder<((MinioClient,), (), ())>;
..Default::default()
}
}
pub fn extra_headers(mut self, extra_headers: Option<Multimap>) -> Self {
self.extra_headers = extra_headers;
self
}
pub fn extra_query_params(mut self, extra_query_params: Option<Multimap>) -> Self {
self.extra_query_params = extra_query_params;
self
}
}
impl S3Api for ListBuckets { impl S3Api for ListBuckets {
type S3Response = ListBucketsResponse; type S3Response = ListBucketsResponse;
@ -56,8 +45,11 @@ impl S3Api for ListBuckets {
impl ToS3Request for ListBuckets { impl ToS3Request for ListBuckets {
fn to_s3request(self) -> Result<S3Request, ValidationErr> { fn to_s3request(self) -> Result<S3Request, ValidationErr> {
Ok(S3Request::new(self.client, Method::GET) Ok(S3Request::builder()
.client(self.client)
.method(Method::GET)
.query_params(self.extra_query_params.unwrap_or_default()) .query_params(self.extra_query_params.unwrap_or_default())
.headers(self.extra_headers.unwrap_or_default())) .headers(self.extra_headers.unwrap_or_default())
.build())
} }
} }

View File

@ -12,7 +12,7 @@
//! Argument builders for ListObject APIs. //! Argument builders for ListObject APIs.
use crate::s3::client::Client; use crate::s3::client::MinioClient;
use crate::s3::error::{Error, ValidationErr}; use crate::s3::error::{Error, ValidationErr};
use crate::s3::multimap_ext::{Multimap, MultimapExt}; use crate::s3::multimap_ext::{Multimap, MultimapExt};
use crate::s3::response::ListObjectsResponse; use crate::s3::response::ListObjectsResponse;
@ -24,6 +24,7 @@ use crate::s3::utils::{check_bucket_name, insert};
use async_trait::async_trait; use async_trait::async_trait;
use futures_util::{Stream, StreamExt, stream as futures_stream}; use futures_util::{Stream, StreamExt, stream as futures_stream};
use http::Method; use http::Method;
use typed_builder::TypedBuilder;
fn add_common_list_objects_query_params( fn add_common_list_objects_query_params(
query_params: &mut Multimap, query_params: &mut Multimap,
@ -55,10 +56,10 @@ fn delim_helper(delim: Option<String>, recursive: bool) -> Option<String> {
/// Argument builder for the [`ListObjectsV1`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjects.html) S3 API operation. /// Argument builder for the [`ListObjectsV1`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjects.html) S3 API operation.
/// ///
/// This struct constructs the parameters required for the [`Client::list_objects`](crate::s3::client::Client::list_objects) method. /// This struct constructs the parameters required for the [`Client::list_objects`](crate::s3::client::MinioClient::list_objects) method.
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug)]
struct ListObjectsV1 { struct ListObjectsV1 {
client: Client, client: MinioClient,
extra_headers: Option<Multimap>, extra_headers: Option<Multimap>,
extra_query_params: Option<Multimap>, extra_query_params: Option<Multimap>,
@ -127,11 +128,14 @@ impl ToS3Request for ListObjectsV1 {
} }
} }
Ok(S3Request::new(self.client, Method::GET) Ok(S3Request::builder()
.client(self.client)
.method(Method::GET)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.query_params(query_params) .query_params(query_params)
.headers(self.extra_headers.unwrap_or_default())) .headers(self.extra_headers.unwrap_or_default())
.build())
} }
} }
@ -157,10 +161,10 @@ impl From<ListObjects> for ListObjectsV1 {
/// Argument builder for the [`ListObjectsV2`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjectsV2.html) S3 API operation. /// Argument builder for the [`ListObjectsV2`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjectsV2.html) S3 API operation.
/// ///
/// This struct constructs the parameters required for the [`Client::list_objects`](crate::s3::client::Client::list_objects) method. /// This struct constructs the parameters required for the [`Client::list_objects`](crate::s3::client::MinioClient::list_objects) method.
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug)]
struct ListObjectsV2 { struct ListObjectsV2 {
client: Client, client: MinioClient,
extra_headers: Option<Multimap>, extra_headers: Option<Multimap>,
extra_query_params: Option<Multimap>, extra_query_params: Option<Multimap>,
@ -242,11 +246,14 @@ impl ToS3Request for ListObjectsV2 {
} }
} }
Ok(S3Request::new(self.client, Method::GET) Ok(S3Request::builder()
.client(self.client)
.method(Method::GET)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.query_params(query_params) .query_params(query_params)
.headers(self.extra_headers.unwrap_or_default())) .headers(self.extra_headers.unwrap_or_default())
.build())
} }
} }
@ -275,10 +282,10 @@ impl From<ListObjects> for ListObjectsV2 {
/// Argument builder for the [`ListObjectVersions`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjectVersions.html) S3 API operation. /// Argument builder for the [`ListObjectVersions`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjectVersions.html) S3 API operation.
/// ///
/// This struct constructs the parameters required for the [`Client::list_objects`](crate::s3::client::Client::list_objects) method. /// This struct constructs the parameters required for the [`Client::list_objects`](crate::s3::client::MinioClient::list_objects) method.
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug)]
struct ListObjectVersions { struct ListObjectVersions {
client: Client, client: MinioClient,
extra_headers: Option<Multimap>, extra_headers: Option<Multimap>,
extra_query_params: Option<Multimap>, extra_query_params: Option<Multimap>,
@ -359,11 +366,14 @@ impl ToS3Request for ListObjectVersions {
} }
} }
Ok(S3Request::new(self.client, Method::GET) Ok(S3Request::builder()
.client(self.client)
.method(Method::GET)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.query_params(query_params) .query_params(query_params)
.headers(self.extra_headers.unwrap_or_default())) .headers(self.extra_headers.unwrap_or_default())
.build())
} }
} }
@ -391,44 +401,115 @@ impl From<ListObjects> for ListObjectVersions {
// region: list-objects // region: list-objects
/// Argument builder for /// Argument builder for
/// [list_objects()](crate::s3::client::Client::list_objects) API. /// [list_objects()](crate::s3::client::MinioClient::list_objects) API.
/// ///
/// Use the various builder methods to set parameters on the request. Finally, to /// Use the various builder methods to set parameters on the request. Finally, to
/// send the request and consume the results. Use the `ToStream` instance to get /// send the request and consume the results. Use the `ToStream` instance to get
/// a stream of results. Pagination is automatically performed. /// a stream of results. Pagination is automatically performed.
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, TypedBuilder)]
pub struct ListObjects { pub struct ListObjects {
client: Client, #[builder(!default)] // force required
client: MinioClient,
// Parameters common to all ListObjects APIs. // Parameters common to all ListObjects APIs.
#[builder(default, setter(into))]
extra_headers: Option<Multimap>, extra_headers: Option<Multimap>,
#[builder(default, setter(into))]
extra_query_params: Option<Multimap>, extra_query_params: Option<Multimap>,
/// Sets the region for the request
#[builder(default, setter(into))]
region: Option<String>, region: Option<String>,
#[builder(setter(into))] // force required + accept Into<String>
bucket: String, bucket: String,
/// Delimiter to roll up common prefixes on.
#[builder(default, setter(into))]
delimiter: Option<String>, delimiter: Option<String>,
/// Disable setting the `EncodingType` parameter in the ListObjects request.
/// By default, it is set to `url`.
#[builder(default)]
disable_url_encoding: bool, disable_url_encoding: bool,
#[builder(default, setter(into))]
max_keys: Option<u16>, max_keys: Option<u16>,
#[builder(default, setter(into))]
prefix: Option<String>, prefix: Option<String>,
// Options specific to ListObjectsV1. // Options specific to ListObjectsV1.
/// Used only with ListObjectsV1.
#[builder(default, setter(into))]
marker: Option<String>, marker: Option<String>,
// Options specific to ListObjectsV2. // Options specific to ListObjectsV2.
/// Used only with ListObjectsV2
#[builder(default, setter(into))]
start_after: Option<String>, start_after: Option<String>,
/// Used only with ListObjectsV2
#[builder(default, setter(into))]
continuation_token: Option<String>, continuation_token: Option<String>,
/// Used only with ListObjectsV2
#[builder(default)]
fetch_owner: bool, fetch_owner: bool,
/// Used only with ListObjectsV2. MinIO extension.
#[builder(default)]
include_user_metadata: bool, include_user_metadata: bool,
// Options specific to ListObjectVersions. // Options specific to ListObjectVersions.
/// Used only with GetObjectVersions.
#[builder(default, setter(into))]
key_marker: Option<String>, key_marker: Option<String>,
/// Used only with GetObjectVersions.
#[builder(default, setter(into))]
version_id_marker: Option<String>, version_id_marker: Option<String>,
// Higher level options. // Higher level options.
/// This parameter takes effect only when delimiter is None. Enables
/// recursive traversal for listing of the bucket and prefix.
#[builder(default)]
recursive: bool, recursive: bool,
/// Set this to use ListObjectsV1. Defaults to false.
/// * For general purpose buckets, ListObjectsV2 returns objects in
/// lexicographical order based on their key names.
/// * For directory buckets (S3-Express), ListObjectsV2 returns objects
/// in an unspecified order implementation-dependent order.
#[builder(default)]
use_api_v1: bool, use_api_v1: bool,
/// Set this to include versions. Defaults to false. Has no effect when
/// `use_api_v1` is set.
#[builder(default)]
include_versions: bool, include_versions: bool,
} }
/// Builder type alias for [`ListObjects`].
///
/// Constructed via [`ListObjects::builder()`](ListObjects::builder) and used to build a [`ListObjects`] instance.
pub type ListObjectBldr = ListObjectsBuilder<(
(MinioClient,),
(),
(),
(),
(String,),
(),
(),
(),
(),
(),
(),
(),
(),
(),
(),
(),
(),
(),
(),
)>;
#[async_trait] #[async_trait]
impl ToStream for ListObjects { impl ToStream for ListObjects {
type Item = ListObjectsResponse; type Item = ListObjectsResponse;
@ -446,118 +527,4 @@ impl ToStream for ListObjects {
} }
} }
} }
impl ListObjects {
pub fn new(client: Client, bucket: String) -> Self {
Self {
client,
bucket,
..Default::default()
}
}
pub fn extra_headers(mut self, extra_headers: Option<Multimap>) -> Self {
self.extra_headers = extra_headers;
self
}
pub fn extra_query_params(mut self, extra_query_params: Option<Multimap>) -> Self {
self.extra_query_params = extra_query_params;
self
}
/// Sets the region for the request
pub fn region(mut self, region: Option<String>) -> Self {
self.region = region;
self
}
/// Delimiter to roll up common prefixes on.
pub fn delimiter(mut self, delimiter: Option<String>) -> Self {
self.delimiter = delimiter;
self
}
/// Disable setting the `EncodingType` parameter in the ListObjects request.
/// By default, it is set to `url`.
pub fn disable_url_encoding(mut self, disable_url_encoding: bool) -> Self {
self.disable_url_encoding = disable_url_encoding;
self
}
pub fn max_keys(mut self, max_keys: Option<u16>) -> Self {
self.max_keys = max_keys;
self
}
pub fn prefix(mut self, prefix: Option<String>) -> Self {
self.prefix = prefix;
self
}
/// Used only with ListObjectsV1.
pub fn marker(mut self, marker: Option<String>) -> Self {
self.marker = marker;
self
}
/// Used only with ListObjectsV2
pub fn start_after(mut self, start_after: Option<String>) -> Self {
self.start_after = start_after;
self
}
/// Used only with ListObjectsV2
pub fn continuation_token(mut self, continuation_token: Option<String>) -> Self {
self.continuation_token = continuation_token;
self
}
/// Used only with ListObjectsV2
pub fn fetch_owner(mut self, fetch_owner: bool) -> Self {
self.fetch_owner = fetch_owner;
self
}
/// Used only with ListObjectsV2. MinIO extension.
pub fn include_user_metadata(mut self, include_user_metadata: bool) -> Self {
self.include_user_metadata = include_user_metadata;
self
}
/// Used only with GetObjectVersions.
pub fn key_marker(mut self, key_marker: Option<String>) -> Self {
self.key_marker = key_marker;
self
}
/// Used only with GetObjectVersions.
pub fn version_id_marker(mut self, version_id_marker: Option<String>) -> Self {
self.version_id_marker = version_id_marker;
self
}
/// This parameter takes effect only when delimiter is None. Enables
/// recursive traversal for listing of the bucket and prefix.
pub fn recursive(mut self, recursive: bool) -> Self {
self.recursive = recursive;
self
}
/// Set this to use ListObjectsV1. Defaults to false.
/// * For general purpose buckets, ListObjectsV2 returns objects in
/// lexicographical order based on their key names.
/// * For directory buckets (S3-Express), ListObjectsV2 returns objects
/// in an unspecified order implementation-dependent order.
pub fn use_api_v1(mut self, use_api_v1: bool) -> Self {
self.use_api_v1 = use_api_v1;
self
}
/// Set this to include versions. Defaults to false. Has no effect when
/// `use_api_v1` is set.
pub fn include_versions(mut self, include_versions: bool) -> Self {
self.include_versions = include_versions;
self
}
}
// endregion: list-objects // endregion: list-objects

View File

@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::client::Client; use crate::s3::client::MinioClient;
use crate::s3::error::{Error, ValidationErr}; use crate::s3::error::{Error, ValidationErr};
use crate::s3::multimap_ext::{Multimap, MultimapExt}; use crate::s3::multimap_ext::{Multimap, MultimapExt};
use crate::s3::response::ListenBucketNotificationResponse; use crate::s3::response::ListenBucketNotificationResponse;
@ -22,63 +22,36 @@ use crate::s3::utils::check_bucket_name;
use async_trait::async_trait; use async_trait::async_trait;
use futures_util::Stream; use futures_util::Stream;
use http::Method; use http::Method;
use typed_builder::TypedBuilder;
/// Argument builder for the [`ListenBucketNotification`](https://min.io/docs/minio/linux/developers/go/API.html#ListenBucketNotification) /// Argument builder for the [`ListenBucketNotification`](https://min.io/docs/minio/linux/developers/go/API.html#ListenBucketNotification)
/// ///
/// This struct constructs the parameters required for the [`Client::listen_bucket_notification`](crate::s3::client::Client::listen_bucket_notification) method. /// This struct constructs the parameters required for the [`Client::listen_bucket_notification`](crate::s3::client::MinioClient::listen_bucket_notification) method.
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, TypedBuilder)]
pub struct ListenBucketNotification { pub struct ListenBucketNotification {
client: Client, #[builder(!default)] // force required
client: MinioClient,
#[builder(default, setter(into))]
extra_headers: Option<Multimap>, extra_headers: Option<Multimap>,
#[builder(default, setter(into))]
extra_query_params: Option<Multimap>, extra_query_params: Option<Multimap>,
#[builder(default, setter(into))]
region: Option<String>, region: Option<String>,
#[builder(setter(into))] // force required + accept Into<String>
bucket: String, bucket: String,
#[builder(default, setter(into))]
prefix: Option<String>, prefix: Option<String>,
#[builder(default, setter(into))]
suffix: Option<String>, suffix: Option<String>,
#[builder(default, setter(into))]
events: Option<Vec<String>>, events: Option<Vec<String>>,
} }
impl ListenBucketNotification { /// Builder type alias for [`ListenBucketNotification`].
pub fn new(client: Client, bucket: String) -> Self { ///
Self { /// Constructed via [`ListenBucketNotification::builder()`](ListenBucketNotification::builder) and used to build a [`ListenBucketNotification`] instance.
client, pub type ListenBucketNotificationBldr =
bucket, ListenBucketNotificationBuilder<((MinioClient,), (), (), (), (String,), (), (), ())>;
..Default::default()
}
}
pub fn extra_headers(mut self, extra_headers: Option<Multimap>) -> Self {
self.extra_headers = extra_headers;
self
}
pub fn extra_query_params(mut self, extra_query_params: Option<Multimap>) -> Self {
self.extra_query_params = extra_query_params;
self
}
/// Sets the region for the request
pub fn region(mut self, region: Option<String>) -> Self {
self.region = region;
self
}
pub fn prefix(mut self, prefix: Option<String>) -> Self {
self.prefix = prefix;
self
}
pub fn suffix(mut self, suffix: Option<String>) -> Self {
self.suffix = suffix;
self
}
pub fn events(mut self, events: Option<Vec<String>>) -> Self {
self.events = events;
self
}
}
#[async_trait] #[async_trait]
impl S3Api for ListenBucketNotification { impl S3Api for ListenBucketNotification {
@ -118,10 +91,13 @@ impl ToS3Request for ListenBucketNotification {
} }
} }
Ok(S3Request::new(self.client, Method::GET) Ok(S3Request::builder()
.client(self.client)
.method(Method::GET)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.query_params(query_params) .query_params(query_params)
.headers(self.extra_headers.unwrap_or_default())) .headers(self.extra_headers.unwrap_or_default())
.build())
} }
} }

View File

@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::Client; use crate::s3::client::MinioClient;
use crate::s3::error::ValidationErr; use crate::s3::error::ValidationErr;
use crate::s3::multimap_ext::Multimap; use crate::s3::multimap_ext::Multimap;
use crate::s3::response::PutBucketEncryptionResponse; use crate::s3::response::PutBucketEncryptionResponse;
@ -22,53 +22,33 @@ use crate::s3::types::{S3Api, S3Request, SseConfig, ToS3Request};
use crate::s3::utils::{check_bucket_name, insert}; use crate::s3::utils::{check_bucket_name, insert};
use bytes::Bytes; use bytes::Bytes;
use http::Method; use http::Method;
use std::sync::Arc;
use typed_builder::TypedBuilder;
/// Argument builder for the [`PutBucketEncryption`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketEncryption.html) S3 API operation. /// Argument builder for the [`PutBucketEncryption`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketEncryption.html) S3 API operation.
/// ///
/// This struct constructs the parameters required for the [`Client::put_bucket_encryption`](crate::s3::client::Client::put_bucket_encryption) method. /// This struct constructs the parameters required for the [`Client::put_bucket_encryption`](crate::s3::client::MinioClient::put_bucket_encryption) method.
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, TypedBuilder)]
pub struct PutBucketEncryption { pub struct PutBucketEncryption {
client: Client, #[builder(!default)] // force required
client: MinioClient,
#[builder(default, setter(into))]
extra_headers: Option<Multimap>, extra_headers: Option<Multimap>,
#[builder(default, setter(into))]
extra_query_params: Option<Multimap>, extra_query_params: Option<Multimap>,
#[builder(default, setter(into))]
region: Option<String>, region: Option<String>,
#[builder(!default, setter(into))] // force required + accept Into<String>
bucket: String, bucket: String,
#[builder(default)]
config: SseConfig, sse_config: SseConfig,
} }
impl PutBucketEncryption { /// Builder type alias for [`PutBucketEncryption`].
pub fn new(client: Client, bucket: String) -> Self { ///
Self { /// Constructed via [`PutBucketEncryption::builder()`](PutBucketEncryption::builder) and used to build a [`PutBucketEncryption`] instance.
client, pub type PutBucketEncryptionBldr =
bucket, PutBucketEncryptionBuilder<((MinioClient,), (), (), (), (String,), ())>;
..Default::default()
}
}
pub fn extra_headers(mut self, extra_headers: Option<Multimap>) -> Self {
self.extra_headers = extra_headers;
self
}
pub fn extra_query_params(mut self, extra_query_params: Option<Multimap>) -> Self {
self.extra_query_params = extra_query_params;
self
}
/// Sets the region for the request
pub fn region(mut self, region: Option<String>) -> Self {
self.region = region;
self
}
/// Sets the server-side encryption configuration for the bucket.
pub fn sse_config(mut self, config: SseConfig) -> Self {
self.config = config;
self
}
}
impl S3Api for PutBucketEncryption { impl S3Api for PutBucketEncryption {
type S3Response = PutBucketEncryptionResponse; type S3Response = PutBucketEncryptionResponse;
@ -78,14 +58,17 @@ impl ToS3Request for PutBucketEncryption {
fn to_s3request(self) -> Result<S3Request, ValidationErr> { fn to_s3request(self) -> Result<S3Request, ValidationErr> {
check_bucket_name(&self.bucket, true)?; check_bucket_name(&self.bucket, true)?;
let bytes: Bytes = self.config.to_xml().into(); let bytes: Bytes = self.sse_config.to_xml().into();
let body: Option<SegmentedBytes> = Some(SegmentedBytes::from(bytes)); let body = Arc::new(SegmentedBytes::from(bytes));
Ok(S3Request::new(self.client, Method::GET) Ok(S3Request::builder()
.client(self.client)
.method(Method::GET)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.query_params(insert(self.extra_query_params, "encryption")) .query_params(insert(self.extra_query_params, "encryption"))
.headers(self.extra_headers.unwrap_or_default()) .headers(self.extra_headers.unwrap_or_default())
.body(body)) .body(body)
.build())
} }
} }

View File

@ -13,62 +13,44 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::Client; use crate::s3::client::MinioClient;
use crate::s3::error::ValidationErr; use crate::s3::error::ValidationErr;
use crate::s3::header_constants::*; use crate::s3::header_constants::*;
use crate::s3::lifecycle_config::LifecycleConfig; use crate::s3::lifecycle_config::LifecycleConfig;
use crate::s3::multimap_ext::{Multimap, MultimapExt}; use crate::s3::multimap_ext::{Multimap, MultimapExt};
use crate::s3::response::PutBucketLifecycleResponse; use crate::s3::response::PutBucketLifecycleResponse;
use crate::s3::segmented_bytes::SegmentedBytes;
use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::types::{S3Api, S3Request, ToS3Request};
use crate::s3::utils::{check_bucket_name, insert, md5sum_hash}; use crate::s3::utils::{check_bucket_name, insert, md5sum_hash};
use bytes::Bytes; use bytes::Bytes;
use http::Method; use http::Method;
use std::sync::Arc;
use typed_builder::TypedBuilder;
/// Argument builder for the [`PutBucketLifecycle`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketLifecycle.html) S3 API operation. /// Argument builder for the [`PutBucketLifecycle`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketLifecycle.html) S3 API operation.
/// ///
/// This struct constructs the parameters required for the [`Client::put_bucket_lifecycle`](crate::s3::client::Client::put_bucket_lifecycle) method. /// This struct constructs the parameters required for the [`Client::put_bucket_lifecycle`](crate::s3::client::MinioClient::put_bucket_lifecycle) method.
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, TypedBuilder)]
pub struct PutBucketLifecycle { pub struct PutBucketLifecycle {
client: Client, #[builder(!default)] // force required
client: MinioClient,
#[builder(default, setter(into))]
extra_headers: Option<Multimap>, extra_headers: Option<Multimap>,
#[builder(default, setter(into))]
extra_query_params: Option<Multimap>, extra_query_params: Option<Multimap>,
#[builder(default, setter(into))]
region: Option<String>, region: Option<String>,
#[builder(!default, setter(into))] // force required + accept Into<String>
bucket: String, bucket: String,
#[builder(default)]
config: LifecycleConfig, life_cycle_config: LifecycleConfig,
} }
impl PutBucketLifecycle { /// Builder type alias for [`PutBucketLifecycle`].
pub fn new(client: Client, bucket: String) -> Self { ///
Self { /// Constructed via [`PutBucketLifecycle::builder()`](PutBucketLifecycle::builder) and used to build a [`PutBucketLifecycle`] instance.
client, pub type PutBucketLifecycleBldr =
bucket, PutBucketLifecycleBuilder<((MinioClient,), (), (), (), (String,), ())>;
..Default::default()
}
}
pub fn extra_headers(mut self, extra_headers: Option<Multimap>) -> Self {
self.extra_headers = extra_headers;
self
}
pub fn extra_query_params(mut self, extra_query_params: Option<Multimap>) -> Self {
self.extra_query_params = extra_query_params;
self
}
/// Sets the region for the request
pub fn region(mut self, region: Option<String>) -> Self {
self.region = region;
self
}
pub fn life_cycle_config(mut self, config: LifecycleConfig) -> Self {
self.config = config;
self
}
}
impl S3Api for PutBucketLifecycle { impl S3Api for PutBucketLifecycle {
type S3Response = PutBucketLifecycleResponse; type S3Response = PutBucketLifecycleResponse;
@ -80,14 +62,19 @@ impl ToS3Request for PutBucketLifecycle {
let mut headers: Multimap = self.extra_headers.unwrap_or_default(); let mut headers: Multimap = self.extra_headers.unwrap_or_default();
let bytes: Bytes = self.config.to_xml().into(); let bytes: Bytes = self.life_cycle_config.to_xml().into();
headers.add(CONTENT_MD5, md5sum_hash(bytes.as_ref())); headers.add(CONTENT_MD5, md5sum_hash(bytes.as_ref()));
Ok(S3Request::new(self.client, Method::PUT) let body = Arc::new(SegmentedBytes::from(bytes));
Ok(S3Request::builder()
.client(self.client)
.method(Method::PUT)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.query_params(insert(self.extra_query_params, "lifecycle")) .query_params(insert(self.extra_query_params, "lifecycle"))
.headers(headers) .headers(headers)
.body(Some(bytes.into()))) .body(body)
.build())
} }
} }

View File

@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::Client; use crate::s3::client::MinioClient;
use crate::s3::error::ValidationErr; use crate::s3::error::ValidationErr;
use crate::s3::multimap_ext::Multimap; use crate::s3::multimap_ext::Multimap;
use crate::s3::response::PutBucketNotificationResponse; use crate::s3::response::PutBucketNotificationResponse;
@ -22,52 +22,33 @@ use crate::s3::types::{NotificationConfig, S3Api, S3Request, ToS3Request};
use crate::s3::utils::{check_bucket_name, insert}; use crate::s3::utils::{check_bucket_name, insert};
use bytes::Bytes; use bytes::Bytes;
use http::Method; use http::Method;
use std::sync::Arc;
use typed_builder::TypedBuilder;
/// Argument builder for the [`PutBucketNotification`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketNotification.html) S3 API operation. /// Argument builder for the [`PutBucketNotification`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketNotification.html) S3 API operation.
/// ///
/// This struct constructs the parameters required for the [`Client::put_bucket_notification`](crate::s3::client::Client::put_bucket_notification) method. /// This struct constructs the parameters required for the [`Client::put_bucket_notification`](crate::s3::client::MinioClient::put_bucket_notification) method.
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, TypedBuilder)]
pub struct PutBucketNotification { pub struct PutBucketNotification {
client: Client, #[builder(!default)] // force required
client: MinioClient,
#[builder(default, setter(into))]
extra_headers: Option<Multimap>, extra_headers: Option<Multimap>,
#[builder(default, setter(into))]
extra_query_params: Option<Multimap>, extra_query_params: Option<Multimap>,
#[builder(default, setter(into))]
region: Option<String>, region: Option<String>,
#[builder(setter(into))] // force required + accept Into<String>
bucket: String, bucket: String,
#[builder(default)]
config: NotificationConfig, notification_config: NotificationConfig,
} }
impl PutBucketNotification { /// Builder type alias for [`PutBucketNotification`].
pub fn new(client: Client, bucket: String) -> Self { ///
Self { /// Constructed via [`PutBucketNotification::builder()`](PutBucketNotification::builder) and used to build a [`PutBucketNotification`] instance.
client, pub type PutBucketNotificationBldr =
bucket, PutBucketNotificationBuilder<((MinioClient,), (), (), (), (String,), ())>;
..Default::default()
}
}
pub fn extra_headers(mut self, extra_headers: Option<Multimap>) -> Self {
self.extra_headers = extra_headers;
self
}
pub fn extra_query_params(mut self, extra_query_params: Option<Multimap>) -> Self {
self.extra_query_params = extra_query_params;
self
}
/// Sets the region for the request
pub fn region(mut self, region: Option<String>) -> Self {
self.region = region;
self
}
pub fn notification_config(mut self, config: NotificationConfig) -> Self {
self.config = config;
self
}
}
impl S3Api for PutBucketNotification { impl S3Api for PutBucketNotification {
type S3Response = PutBucketNotificationResponse; type S3Response = PutBucketNotificationResponse;
@ -77,14 +58,17 @@ impl ToS3Request for PutBucketNotification {
fn to_s3request(self) -> Result<S3Request, ValidationErr> { fn to_s3request(self) -> Result<S3Request, ValidationErr> {
check_bucket_name(&self.bucket, true)?; check_bucket_name(&self.bucket, true)?;
let bytes: Bytes = self.config.to_xml().into(); let bytes: Bytes = self.notification_config.to_xml().into();
let body: Option<SegmentedBytes> = Some(SegmentedBytes::from(bytes)); let body = Arc::new(SegmentedBytes::from(bytes));
Ok(S3Request::new(self.client, Method::PUT) Ok(S3Request::builder()
.client(self.client)
.method(Method::PUT)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.query_params(insert(self.extra_query_params, "notification")) .query_params(insert(self.extra_query_params, "notification"))
.headers(self.extra_headers.unwrap_or_default()) .headers(self.extra_headers.unwrap_or_default())
.body(body)) .body(body)
.build())
} }
} }

View File

@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::Client; use crate::s3::client::MinioClient;
use crate::s3::error::ValidationErr; use crate::s3::error::ValidationErr;
use crate::s3::multimap_ext::Multimap; use crate::s3::multimap_ext::Multimap;
use crate::s3::response::PutBucketPolicyResponse; use crate::s3::response::PutBucketPolicyResponse;
@ -22,52 +22,32 @@ use crate::s3::types::{S3Api, S3Request, ToS3Request};
use crate::s3::utils::{check_bucket_name, insert}; use crate::s3::utils::{check_bucket_name, insert};
use bytes::Bytes; use bytes::Bytes;
use http::Method; use http::Method;
use std::sync::Arc;
use typed_builder::TypedBuilder;
/// Argument builder for the [`PutBucketPolicy`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketPolicy.html) S3 API operation. /// Argument builder for the [`PutBucketPolicy`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketPolicy.html) S3 API operation.
/// ///
/// This struct constructs the parameters required for the [`Client::put_bucket_policy`](crate::s3::client::Client::put_bucket_policy) method. /// This struct constructs the parameters required for the [`Client::put_bucket_policy`](crate::s3::client::MinioClient::put_bucket_policy) method.
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, TypedBuilder)]
pub struct PutBucketPolicy { pub struct PutBucketPolicy {
client: Client, #[builder(!default)] // force required
client: MinioClient,
#[builder(default, setter(into))]
extra_headers: Option<Multimap>, extra_headers: Option<Multimap>,
#[builder(default, setter(into))]
extra_query_params: Option<Multimap>, extra_query_params: Option<Multimap>,
#[builder(default, setter(into))]
region: Option<String>, region: Option<String>,
#[builder(setter(into))] // force required + accept Into<String>
bucket: String, bucket: String,
#[builder(default)]
config: String, //TODO consider PolicyConfig struct config: String, //TODO consider PolicyConfig struct
} }
impl PutBucketPolicy { /// Builder type for [`PutBucketPolicy`] that is returned by [`MinioClient::put_bucket_policy`](crate::s3::client::MinioClient::put_bucket_policy).
pub fn new(client: Client, bucket: String) -> Self { ///
Self { /// This type alias simplifies the complex generic signature generated by the `typed_builder` crate.
client, pub type PutBucketPolicyBldr = PutBucketPolicyBuilder<((MinioClient,), (), (), (), (String,), ())>;
bucket,
..Default::default()
}
}
pub fn extra_headers(mut self, extra_headers: Option<Multimap>) -> Self {
self.extra_headers = extra_headers;
self
}
pub fn extra_query_params(mut self, extra_query_params: Option<Multimap>) -> Self {
self.extra_query_params = extra_query_params;
self
}
/// Sets the region for the request
pub fn region(mut self, region: Option<String>) -> Self {
self.region = region;
self
}
pub fn config(mut self, config: String) -> Self {
self.config = config;
self
}
}
impl S3Api for PutBucketPolicy { impl S3Api for PutBucketPolicy {
type S3Response = PutBucketPolicyResponse; type S3Response = PutBucketPolicyResponse;
@ -78,13 +58,16 @@ impl ToS3Request for PutBucketPolicy {
check_bucket_name(&self.bucket, true)?; check_bucket_name(&self.bucket, true)?;
let bytes: Bytes = self.config.into(); let bytes: Bytes = self.config.into();
let body: Option<SegmentedBytes> = Some(SegmentedBytes::from(bytes)); let body = Arc::new(SegmentedBytes::from(bytes));
Ok(S3Request::new(self.client, Method::PUT) Ok(S3Request::builder()
.client(self.client)
.method(Method::PUT)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.query_params(insert(self.extra_query_params, "policy")) .query_params(insert(self.extra_query_params, "policy"))
.headers(self.extra_headers.unwrap_or_default()) .headers(self.extra_headers.unwrap_or_default())
.body(body)) .body(body)
.build())
} }
} }

View File

@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::Client; use crate::s3::client::MinioClient;
use crate::s3::error::ValidationErr; use crate::s3::error::ValidationErr;
use crate::s3::multimap_ext::Multimap; use crate::s3::multimap_ext::Multimap;
use crate::s3::response::PutBucketReplicationResponse; use crate::s3::response::PutBucketReplicationResponse;
@ -22,52 +22,33 @@ use crate::s3::types::{ReplicationConfig, S3Api, S3Request, ToS3Request};
use crate::s3::utils::{check_bucket_name, insert}; use crate::s3::utils::{check_bucket_name, insert};
use bytes::Bytes; use bytes::Bytes;
use http::Method; use http::Method;
use std::sync::Arc;
use typed_builder::TypedBuilder;
/// Argument builder for the [`PutBucketReplication`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketReplication.html) S3 API operation. /// Argument builder for the [`PutBucketReplication`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketReplication.html) S3 API operation.
/// ///
/// This struct constructs the parameters required for the [`Client::put_bucket_replication`](crate::s3::client::Client::put_bucket_replication) method. /// This struct constructs the parameters required for the [`Client::put_bucket_replication`](crate::s3::client::MinioClient::put_bucket_replication) method.
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, TypedBuilder)]
pub struct PutBucketReplication { pub struct PutBucketReplication {
client: Client, #[builder(!default)] // force required
client: MinioClient,
#[builder(default, setter(into))]
extra_headers: Option<Multimap>, extra_headers: Option<Multimap>,
#[builder(default, setter(into))]
extra_query_params: Option<Multimap>, extra_query_params: Option<Multimap>,
#[builder(default, setter(into))]
region: Option<String>, region: Option<String>,
#[builder(setter(into))] // force required + accept Into<String>
bucket: String, bucket: String,
#[builder(default)]
config: ReplicationConfig, replication_config: ReplicationConfig,
} }
impl PutBucketReplication { /// Builder type for [`PutBucketReplication`] that is returned by [`MinioClient::put_bucket_replication`](crate::s3::client::MinioClient::put_bucket_replication).
pub fn new(client: Client, bucket: String) -> Self { ///
Self { /// This type alias simplifies the complex generic signature generated by the `typed_builder` crate.
client, pub type PutBucketReplicationBldr =
bucket, PutBucketReplicationBuilder<((MinioClient,), (), (), (), (String,), ())>;
..Default::default()
}
}
pub fn extra_headers(mut self, extra_headers: Option<Multimap>) -> Self {
self.extra_headers = extra_headers;
self
}
pub fn extra_query_params(mut self, extra_query_params: Option<Multimap>) -> Self {
self.extra_query_params = extra_query_params;
self
}
/// Sets the region for the request
pub fn region(mut self, region: Option<String>) -> Self {
self.region = region;
self
}
pub fn replication_config(mut self, config: ReplicationConfig) -> Self {
self.config = config;
self
}
}
impl S3Api for PutBucketReplication { impl S3Api for PutBucketReplication {
type S3Response = PutBucketReplicationResponse; type S3Response = PutBucketReplicationResponse;
@ -77,14 +58,17 @@ impl ToS3Request for PutBucketReplication {
fn to_s3request(self) -> Result<S3Request, ValidationErr> { fn to_s3request(self) -> Result<S3Request, ValidationErr> {
check_bucket_name(&self.bucket, true)?; check_bucket_name(&self.bucket, true)?;
let bytes: Bytes = self.config.to_xml().into(); let bytes: Bytes = self.replication_config.to_xml().into();
let body: Option<SegmentedBytes> = Some(SegmentedBytes::from(bytes)); let body = Arc::new(SegmentedBytes::from(bytes));
Ok(S3Request::new(self.client, Method::PUT) Ok(S3Request::builder()
.client(self.client)
.method(Method::PUT)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.query_params(insert(self.extra_query_params, "replication")) .query_params(insert(self.extra_query_params, "replication"))
.headers(self.extra_headers.unwrap_or_default()) .headers(self.extra_headers.unwrap_or_default())
.body(body)) .body(body)
.build())
} }
} }

View File

@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::Client; use crate::s3::client::MinioClient;
use crate::s3::error::ValidationErr; use crate::s3::error::ValidationErr;
use crate::s3::multimap_ext::Multimap; use crate::s3::multimap_ext::Multimap;
use crate::s3::response::PutBucketTaggingResponse; use crate::s3::response::PutBucketTaggingResponse;
@ -23,52 +23,33 @@ use crate::s3::utils::{check_bucket_name, insert};
use bytes::Bytes; use bytes::Bytes;
use http::Method; use http::Method;
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::Arc;
use typed_builder::TypedBuilder;
/// Argument builder for the [`PutBucketTagging`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketTagging.html) S3 API operation. /// Argument builder for the [`PutBucketTagging`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketTagging.html) S3 API operation.
/// ///
/// This struct constructs the parameters required for the [`Client::put_bucket_tagging`](crate::s3::client::Client::put_bucket_tagging) method. /// This struct constructs the parameters required for the [`Client::put_bucket_tagging`](crate::s3::client::MinioClient::put_bucket_tagging) method.
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, TypedBuilder)]
pub struct PutBucketTagging { pub struct PutBucketTagging {
client: Client, #[builder(!default)] // force required
client: MinioClient,
#[builder(default, setter(into))]
extra_headers: Option<Multimap>, extra_headers: Option<Multimap>,
#[builder(default, setter(into))]
extra_query_params: Option<Multimap>, extra_query_params: Option<Multimap>,
#[builder(default, setter(into))]
region: Option<String>, region: Option<String>,
#[builder(setter(into))] // force required + accept Into<String>
bucket: String, bucket: String,
#[builder(default)]
tags: HashMap<String, String>, tags: HashMap<String, String>,
} }
impl PutBucketTagging { /// Builder type for [`PutBucketTagging`] that is returned by [`MinioClient::put_bucket_tagging`](crate::s3::client::MinioClient::put_bucket_tagging).
pub fn new(client: Client, bucket: String) -> Self { ///
Self { /// This type alias simplifies the complex generic signature generated by the `typed_builder` crate.
client, pub type PutBucketTaggingBldr =
bucket, PutBucketTaggingBuilder<((MinioClient,), (), (), (), (String,), ())>;
..Default::default()
}
}
pub fn extra_headers(mut self, extra_headers: Option<Multimap>) -> Self {
self.extra_headers = extra_headers;
self
}
pub fn extra_query_params(mut self, extra_query_params: Option<Multimap>) -> Self {
self.extra_query_params = extra_query_params;
self
}
/// Sets the region for the request
pub fn region(mut self, region: Option<String>) -> Self {
self.region = region;
self
}
pub fn tags(mut self, tags: HashMap<String, String>) -> Self {
self.tags = tags;
self
}
}
impl S3Api for PutBucketTagging { impl S3Api for PutBucketTagging {
type S3Response = PutBucketTaggingResponse; type S3Response = PutBucketTaggingResponse;
@ -97,13 +78,16 @@ impl ToS3Request for PutBucketTagging {
data.push_str("</Tagging>"); data.push_str("</Tagging>");
data data
}; };
let body: Option<SegmentedBytes> = Some(SegmentedBytes::from(Bytes::from(data))); let body = Arc::new(SegmentedBytes::from(Bytes::from(data)));
Ok(S3Request::new(self.client, Method::PUT) Ok(S3Request::builder()
.client(self.client)
.method(Method::PUT)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.query_params(insert(self.extra_query_params, "tagging")) .query_params(insert(self.extra_query_params, "tagging"))
.headers(self.extra_headers.unwrap_or_default()) .headers(self.extra_headers.unwrap_or_default())
.body(body)) .body(body)
.build())
} }
} }

View File

@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::Client; use crate::s3::client::MinioClient;
use crate::s3::error::ValidationErr; use crate::s3::error::ValidationErr;
use crate::s3::multimap_ext::Multimap; use crate::s3::multimap_ext::Multimap;
use crate::s3::response::PutBucketVersioningResponse; use crate::s3::response::PutBucketVersioningResponse;
@ -23,6 +23,8 @@ use crate::s3::utils::{check_bucket_name, insert};
use bytes::Bytes; use bytes::Bytes;
use http::Method; use http::Method;
use std::fmt; use std::fmt;
use std::sync::Arc;
use typed_builder::TypedBuilder;
/// Represents the versioning state of an S3 bucket. /// Represents the versioning state of an S3 bucket.
/// ///
@ -52,22 +54,27 @@ impl fmt::Display for VersioningStatus {
/// Argument builder for the [`PutBucketVersioning`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketVersioning.html) S3 API operation. /// Argument builder for the [`PutBucketVersioning`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketVersioning.html) S3 API operation.
/// ///
/// This struct constructs the parameters required for the [`Client::put_bucket_versioning`](crate::s3::client::Client::put_bucket_versioning) method. /// This struct constructs the parameters required for the [`Client::put_bucket_versioning`](crate::s3::client::MinioClient::put_bucket_versioning) method.
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, TypedBuilder)]
pub struct PutBucketVersioning { pub struct PutBucketVersioning {
/// The S3 client instance used to send the request. /// The S3 client instance used to send the request.
client: Client, #[builder(!default)] // force required
client: MinioClient,
/// Optional additional HTTP headers to include in the request. /// Optional additional HTTP headers to include in the request.
#[builder(default, setter(into))]
extra_headers: Option<Multimap>, extra_headers: Option<Multimap>,
/// Optional additional query parameters to include in the request URL. /// Optional additional query parameters to include in the request URL.
#[builder(default, setter(into))]
extra_query_params: Option<Multimap>, extra_query_params: Option<Multimap>,
/// Optional AWS region to override the client's default region. /// Optional AWS region to override the client's default region.
#[builder(default, setter(into))]
region: Option<String>, region: Option<String>,
/// The name of the bucket for which to configure versioning. /// The name of the bucket for which to configure versioning.
#[builder(setter(into))] // force required + accept Into<String>
bucket: String, bucket: String,
/// Desired versioning status for the bucket. /// Desired versioning status for the bucket.
@ -75,51 +82,23 @@ pub struct PutBucketVersioning {
/// - `Some(VersioningStatus::Enabled)`: Enables versioning. /// - `Some(VersioningStatus::Enabled)`: Enables versioning.
/// - `Some(VersioningStatus::Suspended)`: Suspends versioning. /// - `Some(VersioningStatus::Suspended)`: Suspends versioning.
/// - `None`: No change to the current versioning status. /// - `None`: No change to the current versioning status.
status: Option<VersioningStatus>, #[builder(default, setter(into))]
versioning_status: Option<VersioningStatus>,
/// Specifies whether MFA delete is enabled for the bucket. /// Specifies whether MFA delete is enabled for the bucket.
/// ///
/// - `Some(true)`: Enables MFA delete. /// - `Some(true)`: Enables MFA delete.
/// - `Some(false)`: Disables MFA delete. /// - `Some(false)`: Disables MFA delete.
/// - `None`: No change to the current MFA delete setting. /// - `None`: No change to the current MFA delete setting.
#[builder(default)]
mfa_delete: Option<bool>, mfa_delete: Option<bool>,
} }
impl PutBucketVersioning { /// Builder type for [`PutBucketVersioning`] that is returned by [`MinioClient::put_bucket_versioning`](crate::s3::client::MinioClient::put_bucket_versioning).
pub fn new(client: Client, bucket: String) -> Self { ///
Self { /// This type alias simplifies the complex generic signature generated by the `typed_builder` crate.
client, pub type PutBucketVersioningBldr =
bucket, PutBucketVersioningBuilder<((MinioClient,), (), (), (), (String,), (), ())>;
..Default::default()
}
}
pub fn extra_headers(mut self, extra_headers: Option<Multimap>) -> Self {
self.extra_headers = extra_headers;
self
}
pub fn extra_query_params(mut self, extra_query_params: Option<Multimap>) -> Self {
self.extra_query_params = extra_query_params;
self
}
/// Sets the region for the request
pub fn region(mut self, region: Option<String>) -> Self {
self.region = region;
self
}
pub fn versioning_status(mut self, status: VersioningStatus) -> Self {
self.status = Some(status);
self
}
pub fn mfa_delete(mut self, mfa_delete: Option<bool>) -> Self {
self.mfa_delete = mfa_delete;
self
}
}
impl S3Api for PutBucketVersioning { impl S3Api for PutBucketVersioning {
type S3Response = PutBucketVersioningResponse; type S3Response = PutBucketVersioningResponse;
@ -138,10 +117,11 @@ impl ToS3Request for PutBucketVersioning {
data.push_str("</MFADelete>"); data.push_str("</MFADelete>");
} }
match self.status { match self.versioning_status {
Some(VersioningStatus::Enabled) => data.push_str("<Status>Enabled</Status>"), Some(VersioningStatus::Enabled) => data.push_str("<Status>Enabled</Status>"),
Some(VersioningStatus::Suspended) => data.push_str("<Status>Suspended</Status>"), Some(VersioningStatus::Suspended) => data.push_str("<Status>Suspended</Status>"),
None => { None => {
// TODO this seem inconsistent: `None`: No change to the current versioning status.
return Err(ValidationErr::InvalidVersioningStatus( return Err(ValidationErr::InvalidVersioningStatus(
"Missing VersioningStatus".into(), "Missing VersioningStatus".into(),
)); ));
@ -151,13 +131,16 @@ impl ToS3Request for PutBucketVersioning {
data.push_str("</VersioningConfiguration>"); data.push_str("</VersioningConfiguration>");
data data
}; };
let body: Option<SegmentedBytes> = Some(SegmentedBytes::from(Bytes::from(data))); let body = Arc::new(SegmentedBytes::from(Bytes::from(data)));
Ok(S3Request::new(self.client, Method::PUT) Ok(S3Request::builder()
.client(self.client)
.method(Method::PUT)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.query_params(insert(self.extra_query_params, "versioning")) .query_params(insert(self.extra_query_params, "versioning"))
.headers(self.extra_headers.unwrap_or_default()) .headers(self.extra_headers.unwrap_or_default())
.body(body)) .body(body)
.build())
} }
} }

View File

@ -15,7 +15,7 @@
use super::ObjectContent; use super::ObjectContent;
use crate::s3::builders::{ContentStream, Size}; use crate::s3::builders::{ContentStream, Size};
use crate::s3::client::Client; use crate::s3::client::MinioClient;
use crate::s3::error::{Error, IoError, ValidationErr}; use crate::s3::error::{Error, IoError, ValidationErr};
use crate::s3::header_constants::*; use crate::s3::header_constants::*;
use crate::s3::multimap_ext::{Multimap, MultimapExt}; use crate::s3::multimap_ext::{Multimap, MultimapExt};
@ -32,85 +32,58 @@ use crate::s3::utils::{check_object_name, check_sse, insert};
use bytes::{Bytes, BytesMut}; use bytes::{Bytes, BytesMut};
use http::Method; use http::Method;
use std::{collections::HashMap, sync::Arc}; use std::{collections::HashMap, sync::Arc};
use typed_builder::TypedBuilder;
// region: multipart-upload // region: multipart-upload
/// Argument for /// Argument builder for the [`CreateMultipartUpload`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateMultipartUpload.html) S3 API operation.
/// [create_multipart_upload()](crate::s3::client::Client::create_multipart_upload) ///
/// API /// This struct constructs the parameters required for the [`Client::create_multipart_upload`](crate::s3::client::MinioClient::create_multipart_upload) method.
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, TypedBuilder)]
pub struct CreateMultipartUpload { pub struct CreateMultipartUpload {
client: Client, #[builder(!default)] // force required
client: MinioClient,
#[builder(default, setter(into))]
extra_headers: Option<Multimap>, extra_headers: Option<Multimap>,
#[builder(default, setter(into))]
extra_query_params: Option<Multimap>, extra_query_params: Option<Multimap>,
#[builder(default, setter(into))]
region: Option<String>, region: Option<String>,
#[builder(setter(into))] // force required + accept Into<String>
bucket: String, bucket: String,
#[builder(setter(into))] // force required + accept Into<String>
object: String, object: String,
#[builder(default, setter(into))]
user_metadata: Option<Multimap>, user_metadata: Option<Multimap>,
#[builder(default, setter(into))]
sse: Option<Arc<dyn Sse>>, sse: Option<Arc<dyn Sse>>,
#[builder(default, setter(into))]
tags: Option<HashMap<String, String>>, tags: Option<HashMap<String, String>>,
#[builder(default, setter(into))]
retention: Option<Retention>, retention: Option<Retention>,
#[builder(default = false)]
legal_hold: bool, legal_hold: bool,
#[builder(default, setter(into))]
content_type: Option<String>, content_type: Option<String>,
} }
impl CreateMultipartUpload { /// Builder type for [`CreateMultipartUpload`] that is returned by [`MinioClient::create_multipart_upload`](crate::s3::client::MinioClient::create_multipart_upload).
pub fn new(client: Client, bucket: String, object: String) -> Self { ///
CreateMultipartUpload { /// This type alias simplifies the complex generic signature generated by the `typed_builder` crate.
client, pub type CreateMultipartUploadBldr = CreateMultipartUploadBuilder<(
bucket, (MinioClient,),
object, (),
..Default::default() (),
} (),
} (String,),
(String,),
pub fn extra_headers(mut self, extra_headers: Option<Multimap>) -> Self { (),
self.extra_headers = extra_headers; (),
self (),
} (),
(),
pub fn extra_query_params(mut self, extra_query_params: Option<Multimap>) -> Self { (),
self.extra_query_params = extra_query_params; )>;
self
}
/// Sets the region for the request
pub fn region(mut self, region: Option<String>) -> Self {
self.region = region;
self
}
pub fn user_metadata(mut self, user_metadata: Option<Multimap>) -> Self {
self.user_metadata = user_metadata;
self
}
pub fn sse(mut self, sse: Option<Arc<dyn Sse>>) -> Self {
self.sse = sse;
self
}
pub fn tags(mut self, tags: Option<HashMap<String, String>>) -> Self {
self.tags = tags;
self
}
pub fn retention(mut self, retention: Option<Retention>) -> Self {
self.retention = retention;
self
}
pub fn legal_hold(mut self, legal_hold: bool) -> Self {
self.legal_hold = legal_hold;
self
}
pub fn content_type(mut self, content_type: Option<String>) -> Self {
self.content_type = content_type;
self
}
}
impl S3Api for CreateMultipartUpload { impl S3Api for CreateMultipartUpload {
type S3Response = CreateMultipartUploadResponse; type S3Response = CreateMultipartUploadResponse;
@ -131,12 +104,15 @@ impl ToS3Request for CreateMultipartUpload {
self.content_type, self.content_type,
)?; )?;
Ok(S3Request::new(self.client, Method::POST) Ok(S3Request::builder()
.client(self.client)
.method(Method::POST)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.object(Some(self.object)) .object(self.object)
.query_params(insert(self.extra_query_params, "uploads")) .query_params(insert(self.extra_query_params, "uploads"))
.headers(headers)) .headers(headers)
.build())
} }
} }
@ -145,48 +121,31 @@ impl ToS3Request for CreateMultipartUpload {
// region: abort-multipart-upload // region: abort-multipart-upload
/// Argument for /// Argument for
/// [abort_multipart_upload()](crate::s3::client::Client::abort_multipart_upload) /// [abort_multipart_upload()](crate::s3::client::MinioClient::abort_multipart_upload)
/// API /// API
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, TypedBuilder)]
pub struct AbortMultipartUpload { pub struct AbortMultipartUpload {
client: Client, #[builder(!default)] // force required
client: MinioClient,
#[builder(default, setter(into))]
extra_headers: Option<Multimap>, extra_headers: Option<Multimap>,
#[builder(default, setter(into))]
extra_query_params: Option<Multimap>, extra_query_params: Option<Multimap>,
#[builder(default, setter(into))]
region: Option<String>, region: Option<String>,
#[builder(setter(into))] // force required + accept Into<String>
bucket: String, bucket: String,
#[builder(setter(into))] // force required + accept Into<String>
object: String, object: String,
#[builder(setter(into))] // force required + accept Into<String>
upload_id: String, upload_id: String,
} }
impl AbortMultipartUpload { /// Builder type for [`AbortMultipartUpload`] that is returned by [`MinioClient::abort_multipart_upload`](crate::s3::client::MinioClient::abort_multipart_upload).
pub fn new(client: Client, bucket: String, object: String, upload_id: String) -> Self { ///
Self { /// This type alias simplifies the complex generic signature generated by the `typed_builder` crate.
client, pub type AbortMultipartUploadBldr =
bucket, AbortMultipartUploadBuilder<((MinioClient,), (), (), (), (String,), (String,), (String,))>;
object,
upload_id,
..Default::default()
}
}
pub fn extra_headers(mut self, extra_headers: Option<Multimap>) -> Self {
self.extra_headers = extra_headers;
self
}
pub fn extra_query_params(mut self, extra_query_params: Option<Multimap>) -> Self {
self.extra_query_params = extra_query_params;
self
}
/// Sets the region for the request
pub fn region(mut self, region: Option<String>) -> Self {
self.region = region;
self
}
}
impl S3Api for AbortMultipartUpload { impl S3Api for AbortMultipartUpload {
type S3Response = AbortMultipartUploadResponse; type S3Response = AbortMultipartUploadResponse;
@ -201,12 +160,15 @@ impl ToS3Request for AbortMultipartUpload {
let mut query_params: Multimap = self.extra_query_params.unwrap_or_default(); let mut query_params: Multimap = self.extra_query_params.unwrap_or_default();
query_params.add("uploadId", url_encode(&self.upload_id).to_string()); query_params.add("uploadId", url_encode(&self.upload_id).to_string());
Ok(S3Request::new(self.client, Method::DELETE) Ok(S3Request::builder()
.client(self.client)
.method(Method::DELETE)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.object(Some(self.object)) .object(self.object)
.query_params(query_params) .query_params(query_params)
.headers(headers)) .headers(headers)
.build())
} }
} }
@ -215,60 +177,46 @@ impl ToS3Request for AbortMultipartUpload {
// region: complete-multipart-upload // region: complete-multipart-upload
/// Argument for /// Argument for
/// [complete_multipart_upload()](crate::s3::client::Client::complete_multipart_upload) /// [complete_multipart_upload()](crate::s3::client::MinioClient::complete_multipart_upload)
/// API /// API
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, TypedBuilder)]
pub struct CompleteMultipartUpload { pub struct CompleteMultipartUpload {
client: Client, #[builder(!default)] // force required
client: MinioClient,
#[builder(default, setter(into))]
extra_headers: Option<Multimap>, extra_headers: Option<Multimap>,
#[builder(default, setter(into))]
extra_query_params: Option<Multimap>, extra_query_params: Option<Multimap>,
#[builder(default, setter(into))]
region: Option<String>, region: Option<String>,
#[builder(setter(into))] // force required + accept Into<String>
bucket: String, bucket: String,
#[builder(setter(into))] // force required + accept Into<String>
object: String, object: String,
#[builder(setter(into))] // force required + accept Into<String>
upload_id: String, upload_id: String,
#[builder(!default)] // force required
parts: Vec<PartInfo>, parts: Vec<PartInfo>,
} }
/// Builder type for [`CompleteMultipartUpload`] that is returned by [`MinioClient::complete_multipart_upload`](crate::s3::client::MinioClient::complete_multipart_upload).
///
/// This type alias simplifies the complex generic signature generated by the `typed_builder` crate.
pub type CompleteMultipartUploadBldr = CompleteMultipartUploadBuilder<(
(MinioClient,),
(),
(),
(),
(String,),
(String,),
(String,),
(Vec<PartInfo>,),
)>;
impl S3Api for CompleteMultipartUpload { impl S3Api for CompleteMultipartUpload {
type S3Response = CompleteMultipartUploadResponse; type S3Response = CompleteMultipartUploadResponse;
} }
impl CompleteMultipartUpload {
pub fn new(
client: Client,
bucket: String,
object: String,
upload_id: String,
parts: Vec<PartInfo>,
) -> Self {
Self {
client,
bucket,
object,
upload_id,
parts,
..Default::default()
}
}
pub fn extra_headers(mut self, extra_headers: Option<Multimap>) -> Self {
self.extra_headers = extra_headers;
self
}
pub fn extra_query_params(mut self, extra_query_params: Option<Multimap>) -> Self {
self.extra_query_params = extra_query_params;
self
}
/// Sets the region for the request
pub fn region(mut self, region: Option<String>) -> Self {
self.region = region;
self
}
}
impl ToS3Request for CompleteMultipartUpload { impl ToS3Request for CompleteMultipartUpload {
fn to_s3request(self) -> Result<S3Request, ValidationErr> { fn to_s3request(self) -> Result<S3Request, ValidationErr> {
{ {
@ -307,102 +255,84 @@ impl ToS3Request for CompleteMultipartUpload {
} }
let mut query_params: Multimap = self.extra_query_params.unwrap_or_default(); let mut query_params: Multimap = self.extra_query_params.unwrap_or_default();
query_params.add("uploadId", self.upload_id); query_params.add("uploadId", self.upload_id);
let body = Arc::new(SegmentedBytes::from(bytes));
Ok(S3Request::new(self.client, Method::POST) Ok(S3Request::builder()
.client(self.client)
.method(Method::POST)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.object(Some(self.object)) .object(self.object)
.query_params(query_params) .query_params(query_params)
.headers(headers) .headers(headers)
.body(Some(bytes.into()))) .body(body)
.build())
} }
} }
// endregion: complete-multipart-upload // endregion: complete-multipart-upload
// region: upload-part // region: upload-part
/// Argument for [upload_part()](crate::s3::client::Client::upload_part) S3 API /// Argument for [upload_part()](crate::s3::client::MinioClient::upload_part) S3 API
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, TypedBuilder)]
pub struct UploadPart { pub struct UploadPart {
client: Client, #[builder(!default)] // force required
client: MinioClient,
#[builder(default, setter(into))]
extra_headers: Option<Multimap>, extra_headers: Option<Multimap>,
#[builder(default, setter(into))]
extra_query_params: Option<Multimap>, extra_query_params: Option<Multimap>,
#[builder(setter(into))] // force required + accept Into<String>
bucket: String, bucket: String,
#[builder(setter(into))] // force required + accept Into<String>
object: String, object: String,
#[builder(default, setter(into))]
region: Option<String>, region: Option<String>,
#[builder(default, setter(into))]
sse: Option<Arc<dyn Sse>>, sse: Option<Arc<dyn Sse>>,
#[builder(default, setter(into))]
tags: Option<HashMap<String, String>>, tags: Option<HashMap<String, String>>,
#[builder(default, setter(into))]
retention: Option<Retention>, retention: Option<Retention>,
#[builder(default = false)]
legal_hold: bool, legal_hold: bool,
data: SegmentedBytes, #[builder(!default)] // force required
data: Arc<SegmentedBytes>,
#[builder(default, setter(into))]
content_type: Option<String>, content_type: Option<String>,
// This is used only when this struct is used for PutObject. // This is used only when this struct is used for PutObject.
#[builder(default, setter(into))]
user_metadata: Option<Multimap>, user_metadata: Option<Multimap>,
// These are only used for multipart UploadPart but not for PutObject, so // These are only used for multipart UploadPart but not for PutObject, so
// they are optional. // they are optional.
#[builder(default, setter(into))] // force required
upload_id: Option<String>, upload_id: Option<String>,
#[builder(default, setter(into))] // force required
part_number: Option<u16>, part_number: Option<u16>,
} }
impl UploadPart { /// Builder type for [`UploadPart`] that is returned by [`MinioClient::upload_part`](crate::s3::client::MinioClient::upload_part).
pub fn new( ///
client: Client, /// This type alias simplifies the complex generic signature generated by the `typed_builder` crate.
bucket: String, pub type UploadPartBldr = UploadPartBuilder<(
object: String, (MinioClient,),
upload_id: String, (),
part_number: u16, (),
data: SegmentedBytes, (String,),
) -> Self { (String,),
Self { (),
client, (),
bucket, (),
object, (),
upload_id: Some(upload_id), (),
part_number: Some(part_number), (Arc<SegmentedBytes>,),
data, (),
..Default::default() (),
} (Option<String>,),
} (Option<u16>,),
)>;
pub fn extra_headers(mut self, extra_headers: Option<Multimap>) -> Self {
self.extra_headers = extra_headers;
self
}
pub fn extra_query_params(mut self, extra_query_params: Option<Multimap>) -> Self {
self.extra_query_params = extra_query_params;
self
}
/// Sets the region for the request
pub fn region(mut self, region: Option<String>) -> Self {
self.region = region;
self
}
pub fn sse(mut self, sse: Option<Arc<dyn Sse>>) -> Self {
self.sse = sse;
self
}
pub fn tags(mut self, tags: Option<HashMap<String, String>>) -> Self {
self.tags = tags;
self
}
pub fn retention(mut self, retention: Option<Retention>) -> Self {
self.retention = retention;
self
}
pub fn legal_hold(mut self, legal_hold: bool) -> Self {
self.legal_hold = legal_hold;
self
}
}
impl S3Api for UploadPart { impl S3Api for UploadPart {
type S3Response = UploadPartResponse; type S3Response = UploadPartResponse;
@ -449,13 +379,16 @@ impl ToS3Request for UploadPart {
query_params.add("partNumber", part_number.to_string()); query_params.add("partNumber", part_number.to_string());
} }
Ok(S3Request::new(self.client, Method::PUT) Ok(S3Request::builder()
.client(self.client)
.method(Method::PUT)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.query_params(query_params) .query_params(query_params)
.object(Some(self.object)) .object(self.object)
.headers(headers) .headers(headers)
.body(Some(self.data))) .body(self.data)
.build())
} }
} }
@ -463,70 +396,26 @@ impl ToS3Request for UploadPart {
// region: put-object // region: put-object
/// Argument builder for PutObject S3 API. This is a lower-level API. /// Argument builder for the [`PutObject`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html) S3 API operation.
#[derive(Debug, Clone, Default)] ///
pub struct PutObject(UploadPart); /// This struct constructs the parameters required for the [`Client::put_object`](crate::s3::client::Client::put_object) method.
#[derive(Debug, Clone, TypedBuilder)]
impl PutObject { pub struct PutObject {
pub fn new(client: Client, bucket: String, object: String, data: SegmentedBytes) -> Self { pub(crate) inner: UploadPart,
PutObject(UploadPart {
client,
bucket,
object,
data,
..Default::default()
})
}
pub fn extra_headers(mut self, extra_headers: Option<Multimap>) -> Self {
self.0.extra_headers = extra_headers;
self
}
pub fn extra_query_params(mut self, extra_query_params: Option<Multimap>) -> Self {
self.0.extra_query_params = extra_query_params;
self
}
/// Sets the region for the request
pub fn region(mut self, region: Option<String>) -> Self {
self.0.region = region;
self
}
pub fn user_metadata(mut self, user_metadata: Option<Multimap>) -> Self {
self.0.user_metadata = user_metadata;
self
}
pub fn sse(mut self, sse: Option<Arc<dyn Sse>>) -> Self {
self.0.sse = sse;
self
}
pub fn tags(mut self, tags: Option<HashMap<String, String>>) -> Self {
self.0.tags = tags;
self
}
pub fn retention(mut self, retention: Option<Retention>) -> Self {
self.0.retention = retention;
self
}
pub fn legal_hold(mut self, legal_hold: bool) -> Self {
self.0.legal_hold = legal_hold;
self
}
} }
/// Builder type for [`PutObject`] that is returned by [`MinioClient::put_object`](crate::s3::client::MinioClient::put_object).
///
/// This type alias simplifies the complex generic signature generated by the `typed_builder` crate.
pub type PutObjectBldr = PutObjectBuilder<((UploadPart,),)>;
impl S3Api for PutObject { impl S3Api for PutObject {
type S3Response = PutObjectResponse; type S3Response = PutObjectResponse;
} }
impl ToS3Request for PutObject { impl ToS3Request for PutObject {
fn to_s3request(self) -> Result<S3Request, ValidationErr> { fn to_s3request(self) -> Result<S3Request, ValidationErr> {
self.0.to_s3request() self.inner.to_s3request()
} }
} }
@ -534,102 +423,71 @@ impl ToS3Request for PutObject {
// region: put-object-content // region: put-object-content
/// PutObjectContent takes an `ObjectContent` stream and uploads it to MinIO/S3. /// Argument builder for the [`PutObject`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html) S3 API operation with streaming content.
/// ///
/// It is a higher level API and handles multipart uploads transparently. /// This struct constructs the parameters required for the [`Client::put_object_content`](crate::s3::client::Client::put_object_content) method.
#[derive(Default)] #[derive(TypedBuilder)]
pub struct PutObjectContent { pub struct PutObjectContent {
client: Client, #[builder(!default)] // force required
client: MinioClient,
#[builder(default, setter(into))]
extra_headers: Option<Multimap>, extra_headers: Option<Multimap>,
#[builder(default, setter(into))]
extra_query_params: Option<Multimap>, extra_query_params: Option<Multimap>,
#[builder(default, setter(into))]
region: Option<String>, region: Option<String>,
#[builder(setter(into))] // force required + accept Into<String>
bucket: String, bucket: String,
#[builder(setter(into))] // force required + accept Into<String>
object: String, object: String,
#[builder(default, setter(into))]
user_metadata: Option<Multimap>, user_metadata: Option<Multimap>,
#[builder(default, setter(into))]
sse: Option<Arc<dyn Sse>>, sse: Option<Arc<dyn Sse>>,
#[builder(default, setter(into))]
tags: Option<HashMap<String, String>>, tags: Option<HashMap<String, String>>,
#[builder(default, setter(into))]
retention: Option<Retention>, retention: Option<Retention>,
#[builder(default = false)]
legal_hold: bool, legal_hold: bool,
#[builder(default, setter(into))]
part_size: Size, part_size: Size,
#[builder(default, setter(into))]
content_type: Option<String>, content_type: Option<String>,
// source data // source data
#[builder(!default, setter(into))] // force required + accept Into<String>
input_content: ObjectContent, input_content: ObjectContent,
// Computed. // Computed.
// expected_parts: Option<u16>, // expected_parts: Option<u16>,
#[builder(default, setter(skip))]
content_stream: ContentStream, content_stream: ContentStream,
#[builder(default, setter(skip))]
part_count: Option<u16>, part_count: Option<u16>,
} }
/// Builder type for [`PutObjectContent`] that is returned by [`MinioClient::put_object_content`](crate::s3::client::MinioClient::put_object_content).
///
/// This type alias simplifies the complex generic signature generated by the `typed_builder` crate.
pub type PutObjectContentBldr = PutObjectContentBuilder<(
(MinioClient,),
(),
(),
(),
(String,),
(String,),
(),
(),
(),
(),
(),
(),
(),
(ObjectContent,),
)>;
impl PutObjectContent { impl PutObjectContent {
pub fn new(
client: Client,
bucket: String,
object: String,
content: impl Into<ObjectContent>,
) -> Self {
Self {
client,
bucket,
object,
input_content: content.into(),
..Default::default()
}
}
pub fn extra_headers(mut self, extra_headers: Option<Multimap>) -> Self {
self.extra_headers = extra_headers;
self
}
pub fn extra_query_params(mut self, extra_query_params: Option<Multimap>) -> Self {
self.extra_query_params = extra_query_params;
self
}
/// Sets the region for the request
pub fn region(mut self, region: Option<String>) -> Self {
self.region = region;
self
}
pub fn user_metadata(mut self, user_metadata: Option<Multimap>) -> Self {
self.user_metadata = user_metadata;
self
}
pub fn sse(mut self, sse: Option<Arc<dyn Sse>>) -> Self {
self.sse = sse;
self
}
pub fn tags(mut self, tags: Option<HashMap<String, String>>) -> Self {
self.tags = tags;
self
}
pub fn retention(mut self, retention: Option<Retention>) -> Self {
self.retention = retention;
self
}
pub fn legal_hold(mut self, legal_hold: bool) -> Self {
self.legal_hold = legal_hold;
self
}
pub fn part_size(mut self, part_size: impl Into<Size>) -> Self {
self.part_size = part_size.into();
self
}
pub fn content_type(mut self, content_type: String) -> Self {
self.content_type = Some(content_type);
self
}
pub async fn send(mut self) -> Result<PutObjectContentResponse, Error> { pub async fn send(mut self) -> Result<PutObjectContentResponse, Error> {
check_bucket_name(&self.bucket, true)?; check_bucket_name(&self.bucket, true)?;
check_object_name(&self.object)?; check_object_name(&self.object)?;
@ -667,30 +525,33 @@ impl PutObjectContent {
{ {
let size = seg_bytes.len() as u64; let size = seg_bytes.len() as u64;
let resp: PutObjectResponse = PutObject(UploadPart { let resp: PutObjectResponse = PutObject::builder()
client: self.client.clone(), .inner(UploadPart {
extra_headers: self.extra_headers.clone(), client: self.client.clone(),
extra_query_params: self.extra_query_params.clone(), extra_headers: self.extra_headers.clone(),
bucket: self.bucket.clone(), extra_query_params: self.extra_query_params.clone(),
object: self.object.clone(), bucket: self.bucket.clone(),
region: self.region.clone(), object: self.object.clone(),
user_metadata: self.user_metadata.clone(), region: self.region.clone(),
sse: self.sse.clone(), user_metadata: self.user_metadata.clone(),
tags: self.tags.clone(), sse: self.sse.clone(),
retention: self.retention.clone(), tags: self.tags.clone(),
legal_hold: self.legal_hold, retention: self.retention.clone(),
part_number: None, legal_hold: self.legal_hold,
upload_id: None, part_number: None,
data: seg_bytes, upload_id: None,
content_type: self.content_type.clone(), data: Arc::new(seg_bytes),
}) content_type: self.content_type.clone(),
.send() })
.await?; .build()
.send()
.await?;
Ok(PutObjectContentResponse::new(resp, size)) Ok(PutObjectContentResponse::new(resp, size))
} else if object_size.is_known() && (seg_bytes.len() as u64) < part_size { } else if let Some(expected) = object_size.value()
&& (seg_bytes.len() as u64) < part_size
{
// Not enough data! // Not enough data!
let expected: u64 = object_size.as_u64().unwrap();
let got: u64 = seg_bytes.len() as u64; let got: u64 = seg_bytes.len() as u64;
Err(ValidationErr::InsufficientData { expected, got }.into()) Err(ValidationErr::InsufficientData { expected, got }.into())
} else { } else {
@ -698,22 +559,22 @@ impl PutObjectContent {
let object: String = self.object.clone(); let object: String = self.object.clone();
// Otherwise, we start a multipart upload. // Otherwise, we start a multipart upload.
let create_mpu_resp: CreateMultipartUploadResponse = CreateMultipartUpload { let create_mpu_resp: CreateMultipartUploadResponse = CreateMultipartUpload::builder()
client: self.client.clone(), .client(self.client.clone())
extra_headers: self.extra_headers.clone(), .extra_headers(self.extra_headers.clone())
extra_query_params: self.extra_query_params.clone(), .extra_query_params(self.extra_query_params.clone())
region: self.region.clone(), .region(self.region.clone())
bucket: self.bucket.clone(), .bucket(self.bucket.clone())
object: self.object.clone(), .object(self.object.clone())
user_metadata: self.user_metadata.clone(), .user_metadata(self.user_metadata.clone())
sse: self.sse.clone(), .sse(self.sse.clone())
tags: self.tags.clone(), .tags(self.tags.clone())
retention: self.retention.clone(), .retention(self.retention.clone())
legal_hold: self.legal_hold, .legal_hold(self.legal_hold)
content_type: self.content_type.clone(), .content_type(self.content_type.clone())
} .build()
.send() .send()
.await?; .await?;
let client = self.client.clone(); let client = self.client.clone();
let upload_id: String = create_mpu_resp.upload_id().await?; let upload_id: String = create_mpu_resp.upload_id().await?;
@ -724,7 +585,12 @@ impl PutObjectContent {
if mpu_res.is_err() { if mpu_res.is_err() {
// If we failed to complete the multipart upload, we should abort it. // If we failed to complete the multipart upload, we should abort it.
let _ = AbortMultipartUpload::new(client, bucket, object, upload_id) let _ = AbortMultipartUpload::builder()
.client(client)
.bucket(bucket)
.object(object)
.upload_id(upload_id)
.build()
.send() .send()
.await; .await;
} }
@ -777,8 +643,7 @@ impl PutObjectContent {
return Err(ValidationErr::TooManyParts(part_number as u64).into()); return Err(ValidationErr::TooManyParts(part_number as u64).into());
} }
if object_size.is_known() { if let Some(exp) = object_size.value() {
let exp = object_size.as_u64().unwrap();
if exp < total_read { if exp < total_read {
return Err(ValidationErr::TooMuchData(exp).into()); return Err(ValidationErr::TooMuchData(exp).into());
} }
@ -800,7 +665,7 @@ impl PutObjectContent {
legal_hold: self.legal_hold, legal_hold: self.legal_hold,
part_number: Some(part_number), part_number: Some(part_number),
upload_id: Some(upload_id.to_string()), upload_id: Some(upload_id.to_string()),
data: part_content, data: Arc::new(part_content),
content_type: self.content_type.clone(), content_type: self.content_type.clone(),
} }
.send() .send()
@ -821,8 +686,7 @@ impl PutObjectContent {
// Complete the multipart upload. // Complete the multipart upload.
let size = parts.iter().map(|p| p.size).sum(); let size = parts.iter().map(|p| p.size).sum();
if object_size.is_known() { if let Some(expected) = object_size.value() {
let expected = object_size.as_u64().unwrap();
if expected != size { if expected != size {
return Err(ValidationErr::InsufficientData { return Err(ValidationErr::InsufficientData {
expected, expected,

View File

@ -13,63 +13,55 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::Client; use crate::s3::client::MinioClient;
use crate::s3::error::ValidationErr; use crate::s3::error::ValidationErr;
use crate::s3::header_constants::*; use crate::s3::header_constants::*;
use crate::s3::multimap_ext::{Multimap, MultimapExt}; use crate::s3::multimap_ext::{Multimap, MultimapExt};
use crate::s3::response::PutObjectLegalHoldResponse; use crate::s3::response::PutObjectLegalHoldResponse;
use crate::s3::segmented_bytes::SegmentedBytes;
use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::types::{S3Api, S3Request, ToS3Request};
use crate::s3::utils::{check_bucket_name, check_object_name, insert, md5sum_hash}; use crate::s3::utils::{check_bucket_name, check_object_name, insert, md5sum_hash};
use bytes::Bytes; use bytes::Bytes;
use http::Method; use http::Method;
use std::sync::Arc;
use typed_builder::TypedBuilder;
/// Argument builder for the [`PutObjectLegalHold`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObjectLegalHold.html) S3 API operation. /// Argument builder for the [`PutObjectLegalHold`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObjectLegalHold.html) S3 API operation.
/// ///
/// This struct constructs the parameters required for the [`Client::put_object_legal_hold`](crate::s3::client::Client::put_object_legal_hold) method. /// This struct constructs the parameters required for the [`Client::put_object_legal_hold`](crate::s3::client::MinioClient::put_object_legal_hold) method.
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, TypedBuilder)]
pub struct PutObjectLegalHold { pub struct PutObjectLegalHold {
client: Client, #[builder(!default)] // force required
client: MinioClient,
#[builder(default, setter(into))]
extra_headers: Option<Multimap>, extra_headers: Option<Multimap>,
#[builder(default, setter(into))]
extra_query_params: Option<Multimap>, extra_query_params: Option<Multimap>,
#[builder(default, setter(into))]
region: Option<String>, region: Option<String>,
#[builder(setter(into))] // force required + accept Into<String>
bucket: String, bucket: String,
#[builder(setter(into))] // force required + accept Into<String>
object: String, object: String,
#[builder(default, setter(into))]
version_id: Option<String>, version_id: Option<String>,
#[builder(default, setter(into))]
legal_hold: Option<bool>, legal_hold: Option<bool>,
} }
impl PutObjectLegalHold { /// Builder type for [`PutObjectLegalHold`] that is returned by [`MinioClient::put_object_legal_hold`](crate::s3::client::MinioClient::put_object_legal_hold).
pub fn new(client: Client, bucket: String, object: String) -> Self { ///
Self { /// This type alias simplifies the complex generic signature generated by the `typed_builder` crate.
client, pub type PutObjectLegalHoldBldr = PutObjectLegalHoldBuilder<(
bucket, (MinioClient,),
object, (),
..Default::default() (),
} (),
} (String,),
(String,),
pub fn extra_headers(mut self, extra_headers: Option<Multimap>) -> Self { (),
self.extra_headers = extra_headers; (Option<bool>,),
self )>;
}
pub fn extra_query_params(mut self, extra_query_params: Option<Multimap>) -> Self {
self.extra_query_params = extra_query_params;
self
}
pub fn version_id(mut self, version_id: Option<String>) -> Self {
self.version_id = version_id;
self
}
pub fn legal_hold(mut self, legal_hold: Option<bool>) -> Self {
self.legal_hold = legal_hold;
self
}
}
impl S3Api for PutObjectLegalHold { impl S3Api for PutObjectLegalHold {
type S3Response = PutObjectLegalHoldResponse; type S3Response = PutObjectLegalHoldResponse;
@ -92,13 +84,17 @@ impl ToS3Request for PutObjectLegalHold {
// TODO consider const payload with precalculated md5 // TODO consider const payload with precalculated md5
headers.add(CONTENT_MD5, md5sum_hash(bytes.as_ref())); headers.add(CONTENT_MD5, md5sum_hash(bytes.as_ref()));
let body = Arc::new(SegmentedBytes::from(bytes));
Ok(S3Request::new(self.client, Method::PUT) Ok(S3Request::builder()
.client(self.client)
.method(Method::PUT)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.query_params(query_params) .query_params(query_params)
.headers(headers) .headers(headers)
.object(Some(self.object)) .object(self.object)
.body(Some(bytes.into()))) .body(body)
.build())
} }
} }

View File

@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::Client; use crate::s3::client::MinioClient;
use crate::s3::error::ValidationErr; use crate::s3::error::ValidationErr;
use crate::s3::multimap_ext::Multimap; use crate::s3::multimap_ext::Multimap;
use crate::s3::response::PutObjectLockConfigResponse; use crate::s3::response::PutObjectLockConfigResponse;
@ -22,52 +22,33 @@ use crate::s3::types::{ObjectLockConfig, S3Api, S3Request, ToS3Request};
use crate::s3::utils::{check_bucket_name, insert}; use crate::s3::utils::{check_bucket_name, insert};
use bytes::Bytes; use bytes::Bytes;
use http::Method; use http::Method;
use std::sync::Arc;
use typed_builder::TypedBuilder;
/// Argument builder for the [`PutObjectLockConfig`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObjectLockConfiguration.html) S3 API operation. /// Argument builder for the [`PutObjectLockConfig`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObjectLockConfiguration.html) S3 API operation.
/// ///
/// This struct constructs the parameters required for the [`Client::put_object_lock_config`](crate::s3::client::Client::put_object_lock_config) method. /// This struct constructs the parameters required for the [`Client::put_object_lock_config`](crate::s3::client::MinioClient::put_object_lock_config) method.
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, TypedBuilder)]
pub struct PutObjectLockConfig { pub struct PutObjectLockConfig {
client: Client, #[builder(!default)] // force required
client: MinioClient,
#[builder(default, setter(into))]
extra_headers: Option<Multimap>, extra_headers: Option<Multimap>,
#[builder(default, setter(into))]
extra_query_params: Option<Multimap>, extra_query_params: Option<Multimap>,
#[builder(default, setter(into))]
region: Option<String>, region: Option<String>,
#[builder(setter(into))] // force required + accept Into<String>
bucket: String, bucket: String,
#[builder(default)]
config: ObjectLockConfig, config: ObjectLockConfig,
} }
impl PutObjectLockConfig { /// Builder type for [`PutObjectLockConfig`] that is returned by [`MinioClient::put_object_lock_config`](crate::s3::client::MinioClient::put_object_lock_config).
pub fn new(client: Client, bucket: String) -> Self { ///
Self { /// This type alias simplifies the complex generic signature generated by the `typed_builder` crate.
client, pub type PutObjectLockConfigBldr =
bucket, PutObjectLockConfigBuilder<((MinioClient,), (), (), (), (String,), ())>;
..Default::default()
}
}
pub fn extra_headers(mut self, extra_headers: Option<Multimap>) -> Self {
self.extra_headers = extra_headers;
self
}
pub fn extra_query_params(mut self, extra_query_params: Option<Multimap>) -> Self {
self.extra_query_params = extra_query_params;
self
}
/// Sets the region for the request
pub fn region(mut self, region: Option<String>) -> Self {
self.region = region;
self
}
pub fn config(mut self, config: ObjectLockConfig) -> Self {
self.config = config;
self
}
}
impl S3Api for PutObjectLockConfig { impl S3Api for PutObjectLockConfig {
type S3Response = PutObjectLockConfigResponse; type S3Response = PutObjectLockConfigResponse;
@ -78,13 +59,16 @@ impl ToS3Request for PutObjectLockConfig {
check_bucket_name(&self.bucket, true)?; check_bucket_name(&self.bucket, true)?;
let bytes: Bytes = self.config.to_xml().into(); let bytes: Bytes = self.config.to_xml().into();
let body: Option<SegmentedBytes> = Some(SegmentedBytes::from(bytes)); let body = Arc::new(SegmentedBytes::from(bytes));
Ok(S3Request::new(self.client, Method::PUT) Ok(S3Request::builder()
.client(self.client)
.method(Method::PUT)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.query_params(insert(self.extra_query_params, "object-lock")) .query_params(insert(self.extra_query_params, "object-lock"))
.headers(self.extra_headers.unwrap_or_default()) .headers(self.extra_headers.unwrap_or_default())
.body(body)) .body(body)
.build())
} }
} }

View File

@ -13,83 +13,63 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::Client; use crate::s3::client::MinioClient;
use crate::s3::error::ValidationErr; use crate::s3::error::ValidationErr;
use crate::s3::header_constants::*; use crate::s3::header_constants::*;
use crate::s3::multimap_ext::{Multimap, MultimapExt}; use crate::s3::multimap_ext::{Multimap, MultimapExt};
use crate::s3::response::PutObjectRetentionResponse; use crate::s3::response::PutObjectRetentionResponse;
use crate::s3::segmented_bytes::SegmentedBytes;
use crate::s3::types::{RetentionMode, S3Api, S3Request, ToS3Request}; use crate::s3::types::{RetentionMode, S3Api, S3Request, ToS3Request};
use crate::s3::utils::{ use crate::s3::utils::{
UtcTime, check_bucket_name, check_object_name, insert, md5sum_hash, to_iso8601utc, UtcTime, check_bucket_name, check_object_name, insert, md5sum_hash, to_iso8601utc,
}; };
use bytes::Bytes; use bytes::Bytes;
use http::Method; use http::Method;
use std::sync::Arc;
use typed_builder::TypedBuilder;
/// Argument builder for the [`PutObjectRetention`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObjectRetention.html) S3 API operation. /// Argument builder for the [`PutObjectRetention`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObjectRetention.html) S3 API operation.
/// ///
/// This struct constructs the parameters required for the [`Client::put_object_retention`](crate::s3::client::Client::put_object_retention) method. /// This struct constructs the parameters required for the [`Client::put_object_retention`](crate::s3::client::MinioClient::put_object_retention) method.
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, TypedBuilder)]
pub struct PutObjectRetention { pub struct PutObjectRetention {
client: Client, #[builder(!default)] // force required
client: MinioClient,
#[builder(default, setter(into))]
extra_headers: Option<Multimap>, extra_headers: Option<Multimap>,
#[builder(default, setter(into))]
extra_query_params: Option<Multimap>, extra_query_params: Option<Multimap>,
#[builder(default, setter(into))]
region: Option<String>, region: Option<String>,
#[builder(setter(into))] // force required + accept Into<String>
bucket: String, bucket: String,
#[builder(setter(into))] // force required + accept Into<String>
object: String, object: String,
#[builder(default, setter(into))]
version_id: Option<String>, version_id: Option<String>,
#[builder(default = false)]
bypass_governance_mode: bool, bypass_governance_mode: bool,
#[builder(default, setter(into))]
retention_mode: Option<RetentionMode>, retention_mode: Option<RetentionMode>,
#[builder(default, setter(into))]
retain_until_date: Option<UtcTime>, retain_until_date: Option<UtcTime>,
} }
impl PutObjectRetention { /// Builder type for [`PutObjectRetention`] that is returned by [`MinioClient::put_object_retention`](crate::s3::client::MinioClient::put_object_retention).
pub fn new(client: Client, bucket: String, object: String) -> Self { ///
Self { /// This type alias simplifies the complex generic signature generated by the `typed_builder` crate.
client, pub type PutObjectRetentionBldr = PutObjectRetentionBuilder<(
bucket, (MinioClient,),
object, (),
..Default::default() (),
} (),
} (String,),
(String,),
pub fn extra_headers(mut self, extra_headers: Option<Multimap>) -> Self { (),
self.extra_headers = extra_headers; (),
self (),
} (),
)>;
pub fn extra_query_params(mut self, extra_query_params: Option<Multimap>) -> Self {
self.extra_query_params = extra_query_params;
self
}
/// Sets the region for the request
pub fn region(mut self, region: Option<String>) -> Self {
self.region = region;
self
}
pub fn version_id(mut self, version_id: Option<String>) -> Self {
self.version_id = version_id;
self
}
pub fn bypass_governance_mode(mut self, bypass_governance_mode: bool) -> Self {
self.bypass_governance_mode = bypass_governance_mode;
self
}
pub fn retention_mode(mut self, retention_mode: Option<RetentionMode>) -> Self {
self.retention_mode = retention_mode;
self
}
pub fn retain_until_date(mut self, retain_until_date: Option<UtcTime>) -> Self {
self.retain_until_date = retain_until_date;
self
}
}
impl S3Api for PutObjectRetention { impl S3Api for PutObjectRetention {
type S3Response = PutObjectRetentionResponse; type S3Response = PutObjectRetentionResponse;
@ -133,12 +113,17 @@ impl ToS3Request for PutObjectRetention {
let mut query_params: Multimap = insert(self.extra_query_params, "retention"); let mut query_params: Multimap = insert(self.extra_query_params, "retention");
query_params.add_version(self.version_id); query_params.add_version(self.version_id);
Ok(S3Request::new(self.client, Method::PUT) let body = Arc::new(SegmentedBytes::from(bytes));
Ok(S3Request::builder()
.client(self.client)
.method(Method::PUT)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.query_params(query_params) .query_params(query_params)
.headers(headers) .headers(headers)
.object(Some(self.object)) .object(self.object)
.body(Some(bytes.into()))) .body(body)
.build())
} }
} }

View File

@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::Client; use crate::s3::client::MinioClient;
use crate::s3::error::ValidationErr; use crate::s3::error::ValidationErr;
use crate::s3::multimap_ext::{Multimap, MultimapExt}; use crate::s3::multimap_ext::{Multimap, MultimapExt};
use crate::s3::response::PutObjectTaggingResponse; use crate::s3::response::PutObjectTaggingResponse;
@ -23,60 +23,37 @@ use crate::s3::utils::{check_bucket_name, check_object_name, insert};
use bytes::Bytes; use bytes::Bytes;
use http::Method; use http::Method;
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::Arc;
use typed_builder::TypedBuilder;
/// Argument builder for the [`PutObjectTagging`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObjectTagging.html) S3 API operation. /// Argument builder for the [`PutObjectTagging`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObjectTagging.html) S3 API operation.
/// ///
/// This struct constructs the parameters required for the [`Client::put_object_tagging`](crate::s3::client::Client::put_object_tagging) method. /// This struct constructs the parameters required for the [`Client::put_object_tagging`](crate::s3::client::MinioClient::put_object_tagging) method.
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, TypedBuilder)]
pub struct PutObjectTagging { pub struct PutObjectTagging {
client: Client, #[builder(!default)] // force required
client: MinioClient,
#[builder(default, setter(into))]
extra_headers: Option<Multimap>, extra_headers: Option<Multimap>,
#[builder(default, setter(into))]
extra_query_params: Option<Multimap>, extra_query_params: Option<Multimap>,
#[builder(default, setter(into))]
region: Option<String>, region: Option<String>,
#[builder(setter(into))] // force required + accept Into<String>
bucket: String, bucket: String,
#[builder(setter(into))] // force required + accept Into<String>
object: String, object: String,
#[builder(default, setter(into))]
version_id: Option<String>, version_id: Option<String>,
#[builder(default)]
tags: HashMap<String, String>, tags: HashMap<String, String>,
} }
impl PutObjectTagging { /// Builder type for [`PutObjectTagging`] that is returned by [`MinioClient::put_object_tagging`](crate::s3::client::MinioClient::put_object_tagging).
pub fn new(client: Client, bucket: String, object: String) -> Self { ///
Self { /// This type alias simplifies the complex generic signature generated by the `typed_builder` crate.
client, pub type PutObjectTaggingBldr =
bucket, PutObjectTaggingBuilder<((MinioClient,), (), (), (), (String,), (String,), (), ())>;
object,
..Default::default()
}
}
pub fn extra_headers(mut self, extra_headers: Option<Multimap>) -> Self {
self.extra_headers = extra_headers;
self
}
pub fn extra_query_params(mut self, extra_query_params: Option<Multimap>) -> Self {
self.extra_query_params = extra_query_params;
self
}
/// Sets the region for the request
pub fn region(mut self, region: Option<String>) -> Self {
self.region = region;
self
}
pub fn version_id(mut self, version_id: Option<String>) -> Self {
self.version_id = version_id;
self
}
pub fn tags(mut self, tags: HashMap<String, String>) -> Self {
self.tags = tags;
self
}
}
impl S3Api for PutObjectTagging { impl S3Api for PutObjectTagging {
type S3Response = PutObjectTaggingResponse; type S3Response = PutObjectTaggingResponse;
@ -109,14 +86,17 @@ impl ToS3Request for PutObjectTagging {
data.push_str("</Tagging>"); data.push_str("</Tagging>");
data data
}; };
let body: Option<SegmentedBytes> = Some(SegmentedBytes::from(Bytes::from(data))); let body = Arc::new(SegmentedBytes::from(Bytes::from(data)));
Ok(S3Request::new(self.client, Method::PUT) Ok(S3Request::builder()
.client(self.client)
.method(Method::PUT)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.query_params(query_params) .query_params(query_params)
.object(Some(self.object)) .object(self.object)
.headers(self.extra_headers.unwrap_or_default()) .headers(self.extra_headers.unwrap_or_default())
.body(body)) .body(body)
.build())
} }
} }

View File

@ -13,77 +13,62 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::Client; use crate::s3::client::MinioClient;
use crate::s3::error::ValidationErr; use crate::s3::error::ValidationErr;
use crate::s3::header_constants::*; use crate::s3::header_constants::*;
use crate::s3::multimap_ext::{Multimap, MultimapExt}; use crate::s3::multimap_ext::{Multimap, MultimapExt};
use crate::s3::response::SelectObjectContentResponse; use crate::s3::response::SelectObjectContentResponse;
use crate::s3::segmented_bytes::SegmentedBytes;
use crate::s3::sse::SseCustomerKey; use crate::s3::sse::SseCustomerKey;
use crate::s3::types::{S3Api, S3Request, SelectRequest, ToS3Request}; use crate::s3::types::{S3Api, S3Request, SelectRequest, ToS3Request};
use crate::s3::utils::{check_bucket_name, check_object_name, check_ssec, insert, md5sum_hash}; use crate::s3::utils::{check_bucket_name, check_object_name, check_ssec, insert, md5sum_hash};
use async_trait::async_trait; use async_trait::async_trait;
use bytes::Bytes; use bytes::Bytes;
use http::Method; use http::Method;
use std::sync::Arc;
use typed_builder::TypedBuilder;
/// Argument builder for the [`SelectObjectContent`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_SelectObjectContent.html) S3 API operation. /// Argument builder for the [`SelectObjectContent`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_SelectObjectContent.html) S3 API operation.
/// ///
/// This struct constructs the parameters required for the [`Client::select_object_content`](crate::s3::client::Client::select_object_content) method. /// This struct constructs the parameters required for the [`Client::select_object_content`](crate::s3::client::MinioClient::select_object_content) method.
#[derive(Default)] #[derive(TypedBuilder)]
pub struct SelectObjectContent { pub struct SelectObjectContent {
client: Client, #[builder(!default)] // force required
client: MinioClient,
#[builder(default, setter(into))]
extra_headers: Option<Multimap>, extra_headers: Option<Multimap>,
#[builder(default, setter(into))]
extra_query_params: Option<Multimap>, extra_query_params: Option<Multimap>,
#[builder(default, setter(into))]
region: Option<String>, region: Option<String>,
#[builder(setter(into))] // force required + accept Into<String>
bucket: String, bucket: String,
#[builder(setter(into))] // force required + accept Into<String>
object: String, object: String,
#[builder(default, setter(into))]
version_id: Option<String>, version_id: Option<String>,
#[builder(default, setter(into))]
ssec: Option<SseCustomerKey>, ssec: Option<SseCustomerKey>,
#[builder(default)]
request: SelectRequest, request: SelectRequest,
} }
impl SelectObjectContent { /// Builder type for [`SelectObjectContent`] that is returned by [`MinioClient::select_object_content`](crate::s3::client::MinioClient::select_object_content).
pub fn new(client: Client, bucket: String, object: String) -> Self { ///
Self { /// This type alias simplifies the complex generic signature generated by the `typed_builder` crate.
client, pub type SelectObjectContentBldr = SelectObjectContentBuilder<(
bucket, (MinioClient,),
object, (),
..Default::default() (),
} (),
} (String,),
(String,),
pub fn extra_headers(mut self, extra_headers: Option<Multimap>) -> Self { (),
self.extra_headers = extra_headers; (),
self (SelectRequest,),
} )>;
pub fn extra_query_params(mut self, extra_query_params: Option<Multimap>) -> Self {
self.extra_query_params = extra_query_params;
self
}
/// Sets the region for the request
pub fn region(mut self, region: Option<String>) -> Self {
self.region = region;
self
}
pub fn version_id(mut self, version_id: Option<String>) -> Self {
self.version_id = version_id;
self
}
pub fn ssec(mut self, ssec: Option<SseCustomerKey>) -> Self {
self.ssec = ssec;
self
}
pub fn request(mut self, request: SelectRequest) -> Self {
self.request = request;
self
}
}
impl S3Api for SelectObjectContent { impl S3Api for SelectObjectContent {
type S3Response = SelectObjectContentResponse; type S3Response = SelectObjectContentResponse;
@ -103,13 +88,19 @@ impl ToS3Request for SelectObjectContent {
let mut query_params: Multimap = insert(self.extra_query_params, "select"); let mut query_params: Multimap = insert(self.extra_query_params, "select");
query_params.add("select-type", "2"); query_params.add("select-type", "2");
query_params.add_version(self.version_id);
Ok(S3Request::new(self.client, Method::POST) let body = Arc::new(SegmentedBytes::from(bytes));
Ok(S3Request::builder()
.client(self.client)
.method(Method::POST)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.query_params(query_params) .query_params(query_params)
.headers(headers) .headers(headers)
.object(Some(self.object)) .object(self.object)
.body(Some(bytes.into()))) .body(body)
.build())
} }
} }

View File

@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::client::Client; use crate::s3::client::MinioClient;
use crate::s3::error::ValidationErr; use crate::s3::error::ValidationErr;
use crate::s3::header_constants::*; use crate::s3::header_constants::*;
use crate::s3::multimap_ext::{Multimap, MultimapExt}; use crate::s3::multimap_ext::{Multimap, MultimapExt};
@ -25,98 +25,60 @@ use crate::s3::utils::{
}; };
use async_trait::async_trait; use async_trait::async_trait;
use http::Method; use http::Method;
use typed_builder::TypedBuilder;
/// Argument builder for the [`StatObject`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectAttributes.html) S3 API operation. /// Argument builder for the [`HeadObject`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadObject.html) S3 API operation.
/// Retrieves all of the metadata from an object without returning the object itself.
/// ///
/// This struct constructs the parameters required for the [`Client::stat_object`](crate::s3::client::Client::stat_object) method. /// This struct constructs the parameters required for the [`Client::stat_object`](crate::s3::client::MinioClient::stat_object) method.
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, TypedBuilder)]
pub struct StatObject { pub struct StatObject {
client: Client, #[builder(!default)] // force required
client: MinioClient,
#[builder(default, setter(into))]
extra_headers: Option<Multimap>, extra_headers: Option<Multimap>,
#[builder(default, setter(into))]
extra_query_params: Option<Multimap>, extra_query_params: Option<Multimap>,
#[builder(setter(into))] // force required + accept Into<String>
bucket: String, bucket: String,
#[builder(setter(into))] // force required + accept Into<String>
object: String, object: String,
#[builder(default, setter(into))]
version_id: Option<String>, version_id: Option<String>,
offset: Option<u64>, #[builder(default, setter(into))]
length: Option<u64>,
region: Option<String>, region: Option<String>,
#[builder(default, setter(into))]
ssec: Option<SseCustomerKey>, ssec: Option<SseCustomerKey>,
// Conditionals // Conditionals
#[builder(default, setter(into))]
match_etag: Option<String>, match_etag: Option<String>,
#[builder(default, setter(into))]
not_match_etag: Option<String>, not_match_etag: Option<String>,
#[builder(default, setter(into))]
modified_since: Option<UtcTime>, modified_since: Option<UtcTime>,
#[builder(default, setter(into))]
unmodified_since: Option<UtcTime>, unmodified_since: Option<UtcTime>,
} }
impl StatObject { /// Builder type for [`StatObject`] that is returned by [`MinioClient::stat_object`](crate::s3::client::MinioClient::stat_object).
pub fn new(client: Client, bucket: String, object: String) -> Self { ///
Self { /// This type alias simplifies the complex generic signature generated by the `typed_builder` crate.
client, pub type StatObjectBldr = StatObjectBuilder<(
bucket, (MinioClient,),
object, (),
..Default::default() (),
} (String,),
} (String,),
(),
pub fn extra_headers(mut self, extra_headers: Option<Multimap>) -> Self { (),
self.extra_headers = extra_headers; (),
self (),
} (),
(),
pub fn extra_query_params(mut self, extra_query_params: Option<Multimap>) -> Self { (),
self.extra_query_params = extra_query_params; )>;
self
}
pub fn version_id(mut self, version_id: Option<String>) -> Self {
self.version_id = version_id;
self
}
pub fn offset(mut self, offset: Option<u64>) -> Self {
self.offset = offset;
self
}
pub fn length(mut self, length: Option<u64>) -> Self {
self.length = length;
self
}
/// Sets the region for the request
pub fn region(mut self, region: Option<String>) -> Self {
self.region = region;
self
}
pub fn ssec(mut self, ssec: Option<SseCustomerKey>) -> Self {
self.ssec = ssec;
self
}
pub fn match_etag(mut self, etag: Option<String>) -> Self {
self.match_etag = etag;
self
}
pub fn not_match_etag(mut self, etag: Option<String>) -> Self {
self.not_match_etag = etag;
self
}
pub fn modified_since(mut self, time: Option<UtcTime>) -> Self {
self.modified_since = time;
self
}
pub fn unmodified_since(mut self, time: Option<UtcTime>) -> Self {
self.unmodified_since = time;
self
}
}
impl S3Api for StatObject { impl S3Api for StatObject {
type S3Response = StatObjectResponse; type S3Response = StatObjectResponse;
@ -151,11 +113,14 @@ impl ToS3Request for StatObject {
let mut query_params: Multimap = self.extra_query_params.unwrap_or_default(); let mut query_params: Multimap = self.extra_query_params.unwrap_or_default();
query_params.add_version(self.version_id); query_params.add_version(self.version_id);
Ok(S3Request::new(self.client, Method::GET) Ok(S3Request::builder()
.client(self.client)
.method(Method::GET)
.region(self.region) .region(self.region)
.bucket(Some(self.bucket)) .bucket(self.bucket)
.object(Some(self.object)) .object(self.object)
.query_params(query_params) .query_params(query_params)
.headers(headers)) .headers(headers)
.build())
} }
} }

View File

@ -19,7 +19,7 @@ use bytes::Bytes;
use dashmap::DashMap; use dashmap::DashMap;
use http::HeaderMap; use http::HeaderMap;
use hyper::http::Method; use hyper::http::Method;
use reqwest::{Body, Response}; use reqwest::Body;
use std::fs::File; use std::fs::File;
use std::io::prelude::*; use std::io::prelude::*;
use std::mem; use std::mem;
@ -29,6 +29,8 @@ use uuid::Uuid;
use crate::s3::builders::{BucketExists, ComposeSource}; use crate::s3::builders::{BucketExists, ComposeSource};
use crate::s3::creds::Provider; use crate::s3::creds::Provider;
#[cfg(feature = "localhost")]
use crate::s3::creds::StaticProvider;
use crate::s3::error::{Error, IoError, NetworkError, S3ServerError, ValidationErr}; use crate::s3::error::{Error, IoError, NetworkError, S3ServerError, ValidationErr};
use crate::s3::header_constants::*; use crate::s3::header_constants::*;
use crate::s3::http::BaseUrl; use crate::s3::http::BaseUrl;
@ -120,22 +122,31 @@ pub const MAX_OBJECT_SIZE: u64 = 5_497_558_138_880; // 5 TiB
pub const MAX_MULTIPART_COUNT: u16 = 10_000; pub const MAX_MULTIPART_COUNT: u16 = 10_000;
/// Client Builder manufactures a Client using given parameters. /// Client Builder manufactures a Client using given parameters.
#[derive(Debug, Default)] /// Creates a builder given a base URL for the MinIO service or other AWS S3
pub struct ClientBuilder { /// compatible object storage service.
#[derive(Debug)]
pub struct MinioClientBuilder {
base_url: BaseUrl, base_url: BaseUrl,
/// Set the credential provider. If not, set anonymous access is used.
provider: Option<Arc<dyn Provider + Send + Sync + 'static>>, provider: Option<Arc<dyn Provider + Send + Sync + 'static>>,
/// Set file for loading CAs certs to trust. This is in addition to the system trust store. The file must contain PEM encoded certificates.
ssl_cert_file: Option<PathBuf>, ssl_cert_file: Option<PathBuf>,
/// Set flag to ignore certificate check. This is insecure and should only be used for testing.
ignore_cert_check: Option<bool>, ignore_cert_check: Option<bool>,
/// Set the app info as an Option of (app_name, app_version) pair. This will show up in the client's user-agent.
app_info: Option<(String, String)>, app_info: Option<(String, String)>,
} }
impl ClientBuilder { impl MinioClientBuilder {
/// Creates a builder given a base URL for the MinIO service or other AWS S3 /// Creates a builder given a base URL for the MinIO service or other AWS S3
/// compatible object storage service. /// compatible object storage service.
pub fn new(base_url: BaseUrl) -> Self { pub fn new(base_url: BaseUrl) -> Self {
Self { Self {
base_url, base_url,
..Default::default() provider: None,
ssl_cert_file: None,
ignore_cert_check: None,
app_info: None,
} }
} }
@ -167,7 +178,7 @@ impl ClientBuilder {
} }
/// Build the Client. /// Build the Client.
pub fn build(self) -> Result<Client, Error> { pub fn build(self) -> Result<MinioClient, Error> {
let mut builder = reqwest::Client::builder().no_gzip(); let mut builder = reqwest::Client::builder().no_gzip();
let mut user_agent = String::from("MinIO (") let mut user_agent = String::from("MinIO (")
@ -207,12 +218,13 @@ impl ClientBuilder {
} }
} }
Ok(Client { Ok(MinioClient {
http_client: builder.build().map_err(ValidationErr::from)?, http_client: builder.build().map_err(ValidationErr::from)?,
shared: Arc::new(SharedClientItems { shared: Arc::new(SharedClientItems {
base_url: self.base_url, base_url: self.base_url,
provider: self.provider, provider: self.provider,
..Default::default() region_map: Default::default(),
express: Default::default(),
}), }),
}) })
} }
@ -222,19 +234,19 @@ impl ClientBuilder {
/// ///
/// If credential provider is passed, all S3 operation requests are signed using /// If credential provider is passed, all S3 operation requests are signed using
/// AWS Signature Version 4; else they are performed anonymously. /// AWS Signature Version 4; else they are performed anonymously.
#[derive(Clone, Default, Debug)] #[derive(Clone, Debug)]
pub struct Client { pub struct MinioClient {
http_client: reqwest::Client, http_client: reqwest::Client,
pub(crate) shared: Arc<SharedClientItems>, pub(crate) shared: Arc<SharedClientItems>,
} }
impl Client { impl MinioClient {
/// Returns a S3 client with given base URL. /// Returns a S3 client with given base URL.
/// ///
/// # Examples /// # Examples
/// ///
/// ``` /// ```
/// use minio::s3::client::Client; /// use minio::s3::client::MinioClient;
/// use minio::s3::creds::StaticProvider; /// use minio::s3::creds::StaticProvider;
/// use minio::s3::http::BaseUrl; /// use minio::s3::http::BaseUrl;
/// ///
@ -244,7 +256,7 @@ impl Client {
/// "zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG", /// "zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
/// None, /// None,
/// ); /// );
/// let client = Client::new(base_url, Some(static_provider), None, None).unwrap(); /// let client = MinioClient::new(base_url, Some(static_provider), None, None).unwrap();
/// ``` /// ```
pub fn new<P: Provider + Send + Sync + 'static>( pub fn new<P: Provider + Send + Sync + 'static>(
base_url: BaseUrl, base_url: BaseUrl,
@ -252,7 +264,7 @@ impl Client {
ssl_cert_file: Option<&Path>, ssl_cert_file: Option<&Path>,
ignore_cert_check: Option<bool>, ignore_cert_check: Option<bool>,
) -> Result<Self, Error> { ) -> Result<Self, Error> {
ClientBuilder::new(base_url) MinioClientBuilder::new(base_url)
.provider(provider) .provider(provider)
.ssl_cert_file(ssl_cert_file) .ssl_cert_file(ssl_cert_file)
.ignore_cert_check(ignore_cert_check) .ignore_cert_check(ignore_cert_check)
@ -274,10 +286,12 @@ impl Client {
if let Some(val) = self.shared.express.get() { if let Some(val) = self.shared.express.get() {
*val *val
} else { } else {
// Create a random bucket name let be = BucketExists::builder()
let bucket_name: String = Uuid::new_v4().to_string(); .client(self.clone())
.bucket(Uuid::new_v4().to_string())
.build();
let express = match BucketExists::new(self.clone(), bucket_name).send().await { let express = match be.send().await {
Ok(v) => { Ok(v) => {
if let Some(server) = v.headers().get("server") { if let Some(server) = v.headers().get("server") {
if let Ok(s) = server.to_str() { if let Ok(s) = server.to_str() {
@ -299,6 +313,7 @@ impl Client {
express express
} }
} }
/// Add a bucket-region pair to the region cache if it does not exist. /// Add a bucket-region pair to the region cache if it does not exist.
pub(crate) fn add_bucket_region(&mut self, bucket: &str, region: impl Into<String>) { pub(crate) fn add_bucket_region(&mut self, bucket: &str, region: impl Into<String>) {
self.shared self.shared
@ -351,6 +366,7 @@ impl Client {
.not_match_etag(source.not_match_etag.clone()) .not_match_etag(source.not_match_etag.clone())
.modified_since(source.modified_since) .modified_since(source.modified_since)
.unmodified_since(source.unmodified_since) .unmodified_since(source.unmodified_since)
.build()
.send() .send()
.await?; .await?;
@ -491,13 +507,17 @@ impl Client {
// Sort headers alphabetically by name // Sort headers alphabetically by name
header_strings.sort(); header_strings.sort();
println!( let debug_str = format!(
"S3 request: {} url={:?}; headers={:?}; body={}\n", "S3 request: {method} url={:?}; headers={:?}; body={body:?}",
method,
url.path, url.path,
header_strings.join("; "), header_strings.join("; ")
body.as_ref().unwrap()
); );
let truncated = if debug_str.len() > 1000 {
format!("{}...", &debug_str[..997])
} else {
debug_str
};
println!("{truncated}");
} }
if (*method == Method::PUT) || (*method == Method::POST) { if (*method == Method::PUT) || (*method == Method::POST) {
@ -512,7 +532,7 @@ impl Client {
req = req.body(Body::wrap_stream(stream)); req = req.body(Body::wrap_stream(stream));
} }
let resp: Response = req.send().await.map_err(ValidationErr::from)?; //TODO request error handled by network error layer let resp: reqwest::Response = req.send().await.map_err(ValidationErr::from)?; //TODO request error handled by network error layer
if resp.status().is_success() { if resp.status().is_success() {
return Ok(resp); return Ok(resp);
} }
@ -591,9 +611,24 @@ impl Client {
) )
.await .await
} }
/// create an example client for testing on localhost
#[cfg(feature = "localhost")]
pub fn create_client_on_localhost()
-> Result<MinioClient, Box<dyn std::error::Error + Send + Sync>> {
let base_url = "http://localhost:9000/".parse::<BaseUrl>()?;
log::info!("Trying to connect to MinIO at: `{base_url:?}`");
let static_provider = StaticProvider::new("minioadmin", "minioadmin", None);
let client = MinioClientBuilder::new(base_url.clone())
.provider(Some(static_provider))
.build()?;
Ok(client)
}
} }
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug)]
pub(crate) struct SharedClientItems { pub(crate) struct SharedClientItems {
pub(crate) base_url: BaseUrl, pub(crate) base_url: BaseUrl,
pub(crate) provider: Option<Arc<dyn Provider + Send + Sync + 'static>>, pub(crate) provider: Option<Arc<dyn Provider + Send + Sync + 'static>>,

View File

@ -15,12 +15,14 @@
// ! S3 APIs for appending objects. // ! S3 APIs for appending objects.
use super::Client; use super::MinioClient;
use crate::s3::builders::ObjectContent; use crate::s3::builders::{
use crate::s3::builders::{AppendObject, AppendObjectContent}; AppendObject, AppendObjectBldr, AppendObjectContent, AppendObjectContentBldr, ObjectContent,
};
use crate::s3::segmented_bytes::SegmentedBytes; use crate::s3::segmented_bytes::SegmentedBytes;
use std::sync::Arc;
impl Client { impl MinioClient {
/// Creates a [`AppendObject`] request builder to append data to the end of an (existing) object. /// Creates a [`AppendObject`] request builder to append data to the end of an (existing) object.
/// This is a lower-level API that performs a non-multipart object upload. /// This is a lower-level API that performs a non-multipart object upload.
/// ///
@ -32,7 +34,9 @@ impl Client {
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// use minio::s3::Client; /// use minio::s3::MinioClient;
/// use minio::s3::creds::StaticProvider;
/// use minio::s3::http::BaseUrl;
/// use minio::s3::response::{AppendObjectResponse, PutObjectResponse}; /// use minio::s3::response::{AppendObjectResponse, PutObjectResponse};
/// use minio::s3::segmented_bytes::SegmentedBytes; /// use minio::s3::segmented_bytes::SegmentedBytes;
/// use minio::s3::types::S3Api; /// use minio::s3::types::S3Api;
@ -40,16 +44,18 @@ impl Client {
/// ///
/// #[tokio::main] /// #[tokio::main]
/// async fn main() { /// async fn main() {
/// let client: Client = Default::default(); // configure your client here /// let base_url = "http://localhost:9000/".parse::<BaseUrl>().unwrap();
/// let static_provider = StaticProvider::new("minioadmin", "minioadmin", None);
/// let client = MinioClient::new(base_url, Some(static_provider), None, None).unwrap();
/// let data1: SegmentedBytes = SegmentedBytes::from("aaaa".to_string()); /// let data1: SegmentedBytes = SegmentedBytes::from("aaaa".to_string());
/// let data2: SegmentedBytes = SegmentedBytes::from("bbbb".to_string()); /// let data2: SegmentedBytes = SegmentedBytes::from("bbbb".to_string());
/// let resp: PutObjectResponse = client /// let resp: PutObjectResponse = client
/// .put_object("bucket-name", "object-name", data1) /// .put_object("bucket-name", "object-name", data1)
/// .send().await.unwrap(); /// .build().send().await.unwrap();
/// let offset_bytes = 4; // the offset at which to append the data /// let offset_bytes = 4; // the offset at which to append the data
/// let resp: AppendObjectResponse = client /// let resp: AppendObjectResponse = client
/// .append_object("bucket-name", "object-name", data2, offset_bytes) /// .append_object("bucket-name", "object-name", data2, offset_bytes)
/// .send().await.unwrap(); /// .build().send().await.unwrap();
/// println!("size of the final object is {} bytes", resp.object_size()); /// println!("size of the final object is {} bytes", resp.object_size());
/// } /// }
/// ``` /// ```
@ -59,14 +65,13 @@ impl Client {
object: S2, object: S2,
data: SegmentedBytes, data: SegmentedBytes,
offset_bytes: u64, offset_bytes: u64,
) -> AppendObject { ) -> AppendObjectBldr {
AppendObject::new( AppendObject::builder()
self.clone(), .client(self.clone())
bucket.into(), .bucket(bucket.into())
object.into(), .object(object.into())
data, .data(Arc::new(data))
offset_bytes, .offset_bytes(offset_bytes)
)
} }
/// Creates an [`AppendObjectContent`] request builder to append data to the end of an (existing) /// Creates an [`AppendObjectContent`] request builder to append data to the end of an (existing)
@ -81,7 +86,9 @@ impl Client {
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// use minio::s3::Client; /// use minio::s3::MinioClient;
/// use minio::s3::creds::StaticProvider;
/// use minio::s3::http::BaseUrl;
/// use minio::s3::response::{AppendObjectResponse, PutObjectResponse}; /// use minio::s3::response::{AppendObjectResponse, PutObjectResponse};
/// use minio::s3::builders::ObjectContent; /// use minio::s3::builders::ObjectContent;
/// use minio::s3::segmented_bytes::SegmentedBytes; /// use minio::s3::segmented_bytes::SegmentedBytes;
@ -90,15 +97,17 @@ impl Client {
/// ///
/// #[tokio::main] /// #[tokio::main]
/// async fn main() { /// async fn main() {
/// let client: Client = Default::default(); // configure your client here /// let base_url = "http://localhost:9000/".parse::<BaseUrl>().unwrap();
/// let static_provider = StaticProvider::new("minioadmin", "minioadmin", None);
/// let client = MinioClient::new(base_url, Some(static_provider), None, None).unwrap();
/// let data1: SegmentedBytes = SegmentedBytes::from("aaaa".to_string()); /// let data1: SegmentedBytes = SegmentedBytes::from("aaaa".to_string());
/// let content2: String = "bbbb".to_string(); /// let content2: String = "bbbb".to_string();
/// let resp: PutObjectResponse = client /// let resp: PutObjectResponse = client
/// .put_object("bucket-name", "object-name", data1) /// .put_object("bucket-name", "object-name", data1)
/// .send().await.unwrap(); /// .build().send().await.unwrap();
/// let resp: AppendObjectResponse = client /// let resp: AppendObjectResponse = client
/// .append_object_content("bucket-name", "object-name", content2) /// .append_object_content("bucket-name", "object-name", content2)
/// .send().await.unwrap(); /// .build().send().await.unwrap();
/// println!("size of the final object is {} bytes", resp.object_size()); /// println!("size of the final object is {} bytes", resp.object_size());
/// } /// }
/// ``` /// ```
@ -107,7 +116,11 @@ impl Client {
bucket: S1, bucket: S1,
object: S2, object: S2,
content: C, content: C,
) -> AppendObjectContent { ) -> AppendObjectContentBldr {
AppendObjectContent::new(self.clone(), bucket.into(), object.into(), content) AppendObjectContent::builder()
.client(self.clone())
.bucket(bucket)
.object(object)
.input_content(content)
} }
} }

View File

@ -13,10 +13,10 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use super::Client; use crate::s3::builders::{BucketExists, BucketExistsBldr};
use crate::s3::builders::BucketExists; use crate::s3::client::MinioClient;
impl Client { impl MinioClient {
/// Creates a [`BucketExists`] request builder to check if a bucket exists in S3. /// Creates a [`BucketExists`] request builder to check if a bucket exists in S3.
/// ///
/// To execute the request, call [`BucketExists::send()`](crate::s3::types::S3Api::send), /// To execute the request, call [`BucketExists::send()`](crate::s3::types::S3Api::send),
@ -25,21 +25,25 @@ impl Client {
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// use minio::s3::Client; /// use minio::s3::MinioClient;
/// use minio::s3::creds::StaticProvider;
/// use minio::s3::http::BaseUrl;
/// use minio::s3::response::BucketExistsResponse; /// use minio::s3::response::BucketExistsResponse;
/// use minio::s3::types::S3Api; /// use minio::s3::types::S3Api;
/// use minio::s3::response::a_response_traits::HasBucket; /// use minio::s3::response::a_response_traits::HasBucket;
/// ///
/// #[tokio::main] /// #[tokio::main]
/// async fn main() { /// async fn main() {
/// let client: Client = Default::default(); // configure your client here /// let base_url = "http://localhost:9000/".parse::<BaseUrl>().unwrap();
/// let static_provider = StaticProvider::new("minioadmin", "minioadmin", None);
/// let client = MinioClient::new(base_url, Some(static_provider), None, None).unwrap();
/// let resp: BucketExistsResponse = client /// let resp: BucketExistsResponse = client
/// .bucket_exists("bucket-name") /// .bucket_exists("bucket-name")
/// .send().await.unwrap(); /// .build().send().await.unwrap();
/// println!("bucket '{}' exists: {}", resp.bucket(), resp.exists()); /// println!("bucket '{}' exists: {}", resp.bucket(), resp.exists());
/// } /// }
/// ``` /// ```
pub fn bucket_exists<S: Into<String>>(&self, bucket: S) -> BucketExists { pub fn bucket_exists<S: Into<String>>(&self, bucket: S) -> BucketExistsBldr {
BucketExists::new(self.clone(), bucket.into()) BucketExists::builder().client(self.clone()).bucket(bucket)
} }
} }

View File

@ -13,13 +13,14 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use super::Client;
use crate::s3::builders::{ use crate::s3::builders::{
ComposeObject, ComposeObjectInternal, ComposeSource, CopyObject, CopyObjectInternal, ComposeObject, ComposeObjectBldr, ComposeObjectInternal, ComposeObjectInternalBldr,
UploadPartCopy, ComposeSource, CopyObject, CopyObjectBldr, CopyObjectInternal, CopyObjectInternalBldr,
UploadPartCopy, UploadPartCopyBldr,
}; };
use crate::s3::client::MinioClient;
impl Client { impl MinioClient {
/// Creates a [`UploadPartCopy`] request builder. /// Creates a [`UploadPartCopy`] request builder.
/// See [UploadPartCopy](https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html) S3 API /// See [UploadPartCopy](https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html) S3 API
/// ///
@ -29,7 +30,9 @@ impl Client {
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// use minio::s3::Client; /// use minio::s3::MinioClient;
/// use minio::s3::creds::StaticProvider;
/// use minio::s3::http::BaseUrl;
/// use minio::s3::response::UploadPartCopyResponse; /// use minio::s3::response::UploadPartCopyResponse;
/// use minio::s3::segmented_bytes::SegmentedBytes; /// use minio::s3::segmented_bytes::SegmentedBytes;
/// use minio::s3::types::S3Api; /// use minio::s3::types::S3Api;
@ -37,12 +40,14 @@ impl Client {
/// ///
/// #[tokio::main] /// #[tokio::main]
/// async fn main() { /// async fn main() {
/// let client: Client = Default::default(); // configure your client here /// let base_url = "http://localhost:9000/".parse::<BaseUrl>().unwrap();
/// let static_provider = StaticProvider::new("minioadmin", "minioadmin", None);
/// let client = MinioClient::new(base_url, Some(static_provider), None, None).unwrap();
/// let data1: SegmentedBytes = SegmentedBytes::from("aaaa".to_string()); /// let data1: SegmentedBytes = SegmentedBytes::from("aaaa".to_string());
/// todo!(); /// todo!();
/// let resp: UploadPartCopyResponse = client /// let resp: UploadPartCopyResponse = client
/// .upload_part_copy("bucket-name", "object-name", "TODO") /// .upload_part_copy("bucket-name", "object-name", "TODO")
/// .send().await.unwrap(); /// .build().send().await.unwrap();
/// println!("uploaded {}", resp.object()); /// println!("uploaded {}", resp.object());
/// } /// }
/// ``` /// ```
@ -51,8 +56,12 @@ impl Client {
bucket: S1, bucket: S1,
object: S2, object: S2,
upload_id: S3, upload_id: S3,
) -> UploadPartCopy { ) -> UploadPartCopyBldr {
UploadPartCopy::new(self.clone(), bucket.into(), object.into(), upload_id.into()) UploadPartCopy::builder()
.client(self.clone())
.bucket(bucket)
.object(object)
.upload_id(upload_id)
} }
/// Create a CopyObject request builder. This is a lower-level API that /// Create a CopyObject request builder. This is a lower-level API that
@ -61,8 +70,11 @@ impl Client {
&self, &self,
bucket: S1, bucket: S1,
object: S2, object: S2,
) -> CopyObjectInternal { ) -> CopyObjectInternalBldr {
CopyObjectInternal::new(self.clone(), bucket.into(), object.into()) CopyObjectInternal::builder()
.client(self.clone())
.bucket(bucket)
.object(object)
} }
/// Create a CopyObject request builder. /// Create a CopyObject request builder.
@ -74,9 +86,9 @@ impl Client {
/// The destination of the copy is specified via the `bucket` and `object` parameters of this function. /// The destination of the copy is specified via the `bucket` and `object` parameters of this function.
/// To specify the source object to be copied, call `.source(...)` on the returned [`CopyObject`] builder. /// To specify the source object to be copied, call `.source(...)` on the returned [`CopyObject`] builder.
/// ///
/// Internally, this function first performs a [`stat_object`](Client::stat_object) call /// Internally, this function first performs a [`stat_object`](MinioClient::stat_object) call
/// to retrieve metadata about the source object. It then constructs a /// to retrieve metadata about the source object. It then constructs a
/// [`compose_object`](Client::compose_object) request to perform the actual copy. /// [`compose_object`](MinioClient::compose_object) request to perform the actual copy.
/// ///
/// # Arguments /// # Arguments
/// ///
@ -86,7 +98,9 @@ impl Client {
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// use minio::s3::Client; /// use minio::s3::MinioClient;
/// use minio::s3::creds::StaticProvider;
/// use minio::s3::http::BaseUrl;
/// use minio::s3::response::CopyObjectResponse; /// use minio::s3::response::CopyObjectResponse;
/// use minio::s3::builders::CopySource; /// use minio::s3::builders::CopySource;
/// use minio::s3::types::S3Api; /// use minio::s3::types::S3Api;
@ -94,11 +108,13 @@ impl Client {
/// #[tokio::main] /// #[tokio::main]
/// async fn main() { /// async fn main() {
/// use minio::s3::response::a_response_traits::HasVersion; /// use minio::s3::response::a_response_traits::HasVersion;
/// let client: Client = Default::default(); // configure your client here /// let base_url = "http://localhost:9000/".parse::<BaseUrl>().unwrap();
/// let static_provider = StaticProvider::new("minioadmin", "minioadmin", None);
/// let client = MinioClient::new(base_url, Some(static_provider), None, None).unwrap();
/// let resp: CopyObjectResponse = client /// let resp: CopyObjectResponse = client
/// .copy_object("bucket-name-dst", "object-name-dst") /// .copy_object("bucket-name-dst", "object-name-dst")
/// .source(CopySource::new("bucket-name-src", "object-name-src").unwrap()) /// .source(CopySource::builder().bucket("bucket-name-src").object("object-name-src").build())
/// .send().await.unwrap(); /// .build().send().await.unwrap();
/// println!("copied the file from src to dst. New version: {:?}", resp.version_id()); /// println!("copied the file from src to dst. New version: {:?}", resp.version_id());
/// } /// }
/// ``` /// ```
@ -106,8 +122,11 @@ impl Client {
&self, &self,
bucket: S1, bucket: S1,
object: S2, object: S2,
) -> CopyObject { ) -> CopyObjectBldr {
CopyObject::new(self.clone(), bucket.into(), object.into()) CopyObject::builder()
.client(self.clone())
.bucket(bucket)
.object(object)
} }
/// Create a ComposeObjectInternal request builder. This is a higher-level API that /// Create a ComposeObjectInternal request builder. This is a higher-level API that
@ -116,18 +135,25 @@ impl Client {
&self, &self,
bucket: S1, bucket: S1,
object: S2, object: S2,
) -> ComposeObjectInternal { ) -> ComposeObjectInternalBldr {
ComposeObjectInternal::new(self.clone(), bucket.into(), object.into()) ComposeObjectInternal::builder()
.client(self.clone())
.bucket(bucket)
.object(object)
} }
/// compose object is higher-level API that calls an internal compose object, and if that call fails, /// compose object is higher-level API that calls an internal compose object, and if that call fails,
/// it calls ['abort_multipart_upload`](Client::abort_multipart_upload). /// it calls ['abort_multipart_upload`](MinioClient::abort_multipart_upload).
pub fn compose_object<S1: Into<String>, S2: Into<String>>( pub fn compose_object<S1: Into<String>, S2: Into<String>>(
&self, &self,
bucket: S1, bucket: S1,
object: S2, object: S2,
sources: Vec<ComposeSource>, sources: Vec<ComposeSource>,
) -> ComposeObject { ) -> ComposeObjectBldr {
ComposeObject::new(self.clone(), bucket.into(), object.into()).sources(sources) ComposeObject::builder()
.client(self.clone())
.bucket(bucket)
.object(object)
.sources(sources)
} }
} }

View File

@ -13,10 +13,10 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use super::Client; use crate::s3::builders::{CreateBucket, CreateBucketBldr};
use crate::s3::builders::CreateBucket; use crate::s3::client::MinioClient;
impl Client { impl MinioClient {
/// Creates a [`CreateBucket`] request builder. /// Creates a [`CreateBucket`] request builder.
/// ///
/// To execute the request, call [`CreateBucket::send()`](crate::s3::types::S3Api::send), /// To execute the request, call [`CreateBucket::send()`](crate::s3::types::S3Api::send),
@ -25,21 +25,25 @@ impl Client {
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// use minio::s3::Client; /// use minio::s3::MinioClient;
/// use minio::s3::creds::StaticProvider;
/// use minio::s3::http::BaseUrl;
/// use minio::s3::response::CreateBucketResponse; /// use minio::s3::response::CreateBucketResponse;
/// use minio::s3::types::S3Api; /// use minio::s3::types::S3Api;
/// use minio::s3::response::a_response_traits::{HasBucket, HasRegion}; /// use minio::s3::response::a_response_traits::{HasBucket, HasRegion};
/// ///
/// #[tokio::main] /// #[tokio::main]
/// async fn main() { /// async fn main() {
/// let client: Client = Default::default(); // configure your client here /// let base_url = "http://localhost:9000/".parse::<BaseUrl>().unwrap();
/// let static_provider = StaticProvider::new("minioadmin", "minioadmin", None);
/// let client = MinioClient::new(base_url, Some(static_provider), None, None).unwrap();
/// let resp: CreateBucketResponse = client /// let resp: CreateBucketResponse = client
/// .create_bucket("bucket-name") /// .create_bucket("bucket-name")
/// .send().await.unwrap(); /// .build().send().await.unwrap();
/// println!("Made bucket '{}' in region '{}'", resp.bucket(), resp.region()); /// println!("Made bucket '{}' in region '{}'", resp.bucket(), resp.region());
/// } /// }
/// ``` /// ```
pub fn create_bucket<S: Into<String>>(&self, bucket: S) -> CreateBucket { pub fn create_bucket<S: Into<String>>(&self, bucket: S) -> CreateBucketBldr {
CreateBucket::new(self.clone(), bucket.into()) CreateBucket::builder().client(self.clone()).bucket(bucket)
} }
} }

View File

@ -13,20 +13,22 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use super::Client; use crate::s3::builders::{DeleteBucket, DeleteBucketBldr, DeleteObject, ObjectToDelete};
use crate::s3::builders::{DeleteBucket, DeleteObject, ObjectToDelete}; use crate::s3::client::MinioClient;
use crate::s3::error::Error; use crate::s3::error::Error;
use crate::s3::error::S3ServerError::S3Error; use crate::s3::error::S3ServerError::S3Error;
use crate::s3::minio_error_response::MinioErrorCode; use crate::s3::minio_error_response::MinioErrorCode;
use crate::s3::response::{BucketExistsResponse, DeleteResult};
use crate::s3::response::{ use crate::s3::response::{
DeleteBucketResponse, DeleteObjectResponse, DeleteObjectsResponse, PutObjectLegalHoldResponse, BucketExistsResponse, DeleteBucketResponse, DeleteObjectResponse, DeleteObjectsResponse,
DeleteResult, PutObjectLegalHoldResponse,
}; };
use crate::s3::types::{S3Api, ToStream}; use crate::s3::types::{S3Api, S3Request, ToStream};
use bytes::Bytes; use bytes::Bytes;
use futures_util::StreamExt; use futures_util::StreamExt;
use http::Method;
use multimap::MultiMap;
impl Client { impl MinioClient {
/// Creates a [`DeleteBucket`] request builder. /// Creates a [`DeleteBucket`] request builder.
/// ///
/// To execute the request, call [`DeleteBucket::send()`](crate::s3::types::S3Api::send), /// To execute the request, call [`DeleteBucket::send()`](crate::s3::types::S3Api::send),
@ -35,21 +37,26 @@ impl Client {
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// use minio::s3::Client; /// use minio::s3::MinioClient;
/// use minio::s3::creds::StaticProvider;
/// use minio::s3::http::BaseUrl;
/// use minio::s3::response::DeleteBucketResponse; /// use minio::s3::response::DeleteBucketResponse;
/// use minio::s3::types::S3Api; /// use minio::s3::types::S3Api;
/// use minio::s3::response::a_response_traits::{HasBucket, HasRegion}; /// use minio::s3::response::a_response_traits::{HasBucket, HasRegion};
/// ///
/// #[tokio::main] /// #[tokio::main]
/// async fn main() { /// async fn main() {
/// let client: Client = Default::default(); // configure your client here /// let base_url = "http://localhost:9000/".parse::<BaseUrl>().unwrap();
/// let resp: DeleteBucketResponse = /// let static_provider = StaticProvider::new("minioadmin", "minioadmin", None);
/// client.delete_bucket("bucket-name").send().await.unwrap(); /// let client = MinioClient::new(base_url, Some(static_provider), None, None).unwrap();
/// let resp: DeleteBucketResponse = client
/// .delete_bucket("bucket-name")
/// .build().send().await.unwrap();
/// println!("bucket '{}' in region '{}' is removed", resp.bucket(), resp.region()); /// println!("bucket '{}' in region '{}' is removed", resp.bucket(), resp.region());
/// } /// }
/// ``` /// ```
pub fn delete_bucket<S: Into<String>>(&self, bucket: S) -> DeleteBucket { pub fn delete_bucket<S: Into<String>>(&self, bucket: S) -> DeleteBucketBldr {
DeleteBucket::new(self.clone(), bucket.into()) DeleteBucket::builder().client(self.clone()).bucket(bucket)
} }
/// Deletes a bucket and also deletes non-empty buckets by first removing all objects before /// Deletes a bucket and also deletes non-empty buckets by first removing all objects before
@ -60,11 +67,18 @@ impl Client {
) -> Result<DeleteBucketResponse, Error> { ) -> Result<DeleteBucketResponse, Error> {
let bucket: String = bucket.into(); let bucket: String = bucket.into();
let resp: BucketExistsResponse = self.bucket_exists(&bucket).send().await?; let resp: BucketExistsResponse = self.bucket_exists(&bucket).build().send().await?;
if !resp.exists { if !resp.exists {
// if the bucket does not exist, we can return early // if the bucket does not exist, we can return early
let dummy: S3Request = S3Request::builder()
.client(self.clone())
.method(Method::DELETE)
.bucket(bucket)
.headers(MultiMap::default())
.build();
return Ok(DeleteBucketResponse { return Ok(DeleteBucketResponse {
request: Default::default(), //TODO consider how to handle this request: dummy, //TODO consider how to handle this
body: Bytes::new(), body: Bytes::new(),
headers: Default::default(), headers: Default::default(),
}); });
@ -76,6 +90,7 @@ impl Client {
.list_objects(&bucket) .list_objects(&bucket)
.include_versions(!is_express) .include_versions(!is_express)
.recursive(true) .recursive(true)
.build()
.to_stream() .to_stream()
.await; .await;
@ -111,17 +126,18 @@ impl Client {
let _resp: PutObjectLegalHoldResponse = self let _resp: PutObjectLegalHoldResponse = self
.put_object_legal_hold(&bucket, &v.object_name, false) .put_object_legal_hold(&bucket, &v.object_name, false)
.version_id(v.version_id.clone()) .version_id(v.version_id.clone())
.build()
.send() .send()
.await?; .await?;
let _resp: DeleteObjectResponse = DeleteObject::new( let _resp: DeleteObjectResponse = DeleteObject::builder()
self.clone(), .client(self.clone())
bucket.clone(), .bucket(bucket.clone())
ObjectToDelete::from(v), .object(v)
) .bypass_governance_mode(true)
.bypass_governance_mode(true) .build()
.send() .send()
.await?; .await?;
} }
} }
} }
@ -129,13 +145,20 @@ impl Client {
} }
} }
let request: DeleteBucket = self.delete_bucket(&bucket); let request: DeleteBucket = self.delete_bucket(&bucket).build();
match request.send().await { match request.send().await {
Ok(resp) => Ok(resp), Ok(resp) => Ok(resp),
Err(Error::S3Server(S3Error(mut e))) => { Err(Error::S3Server(S3Error(mut e))) => {
if matches!(e.code(), MinioErrorCode::NoSuchBucket) { if matches!(e.code(), MinioErrorCode::NoSuchBucket) {
let dummy: S3Request = S3Request::builder()
.client(self.clone())
.method(Method::DELETE)
.bucket(bucket)
.headers(MultiMap::default())
.build();
Ok(DeleteBucketResponse { Ok(DeleteBucketResponse {
request: Default::default(), //TODO consider how to handle this request: dummy, //TODO consider how to handle this
body: Bytes::new(), body: Bytes::new(),
headers: e.take_headers(), headers: e.take_headers(),
}) })
@ -146,6 +169,7 @@ impl Client {
.list_objects(&bucket) .list_objects(&bucket)
.include_versions(!is_express) .include_versions(!is_express)
.recursive(true) .recursive(true)
.build()
.to_stream() .to_stream()
.await; .await;

View File

@ -13,10 +13,10 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use super::Client; use crate::s3::builders::{DeleteBucketEncryption, DeleteBucketEncryptionBldr};
use crate::s3::builders::DeleteBucketEncryption; use crate::s3::client::MinioClient;
impl Client { impl MinioClient {
/// Creates a [`DeleteBucketEncryption`] request builder. /// Creates a [`DeleteBucketEncryption`] request builder.
/// ///
/// To execute the request, call [`DeleteBucketEncryption::send()`](crate::s3::types::S3Api::send), /// To execute the request, call [`DeleteBucketEncryption::send()`](crate::s3::types::S3Api::send),
@ -25,21 +25,30 @@ impl Client {
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// use minio::s3::Client; /// use minio::s3::MinioClient;
/// use minio::s3::creds::StaticProvider;
/// use minio::s3::http::BaseUrl;
/// use minio::s3::response::DeleteBucketEncryptionResponse; /// use minio::s3::response::DeleteBucketEncryptionResponse;
/// use minio::s3::types::S3Api; /// use minio::s3::types::S3Api;
/// use minio::s3::response::a_response_traits::HasBucket; /// use minio::s3::response::a_response_traits::HasBucket;
/// ///
/// #[tokio::main] /// #[tokio::main]
/// async fn main() { /// async fn main() {
/// let client: Client = Default::default(); // configure your client here /// let base_url = "http://localhost:9000/".parse::<BaseUrl>().unwrap();
/// let static_provider = StaticProvider::new("minioadmin", "minioadmin", None);
/// let client = MinioClient::new(base_url, Some(static_provider), None, None).unwrap();
/// let resp: DeleteBucketEncryptionResponse = client /// let resp: DeleteBucketEncryptionResponse = client
/// .delete_bucket_encryption("bucket-name") /// .delete_bucket_encryption("bucket-name")
/// .send().await.unwrap(); /// .build().send().await.unwrap();
/// println!("bucket '{}' is deleted", resp.bucket()); /// println!("bucket '{}' is deleted", resp.bucket());
/// } /// }
/// ``` /// ```
pub fn delete_bucket_encryption<S: Into<String>>(&self, bucket: S) -> DeleteBucketEncryption { pub fn delete_bucket_encryption<S: Into<String>>(
DeleteBucketEncryption::new(self.clone(), bucket.into()) &self,
bucket: S,
) -> DeleteBucketEncryptionBldr {
DeleteBucketEncryption::builder()
.client(self.clone())
.bucket(bucket)
} }
} }

View File

@ -13,10 +13,10 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use super::Client; use crate::s3::builders::{DeleteBucketLifecycle, DeleteBucketLifecycleBldr};
use crate::s3::builders::DeleteBucketLifecycle; use crate::s3::client::MinioClient;
impl Client { impl MinioClient {
/// Creates a [`DeleteBucketLifecycle`] request builder. /// Creates a [`DeleteBucketLifecycle`] request builder.
/// ///
/// To execute the request, call [`DeleteBucketLifecycle::send()`](crate::s3::types::S3Api::send), /// To execute the request, call [`DeleteBucketLifecycle::send()`](crate::s3::types::S3Api::send),
@ -25,21 +25,27 @@ impl Client {
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// use minio::s3::Client; /// use minio::s3::MinioClient;
/// use minio::s3::creds::StaticProvider;
/// use minio::s3::http::BaseUrl;
/// use minio::s3::response::DeleteBucketLifecycleResponse; /// use minio::s3::response::DeleteBucketLifecycleResponse;
/// use minio::s3::types::S3Api; /// use minio::s3::types::S3Api;
/// use minio::s3::response::a_response_traits::HasBucket; /// use minio::s3::response::a_response_traits::HasBucket;
/// ///
/// #[tokio::main] /// #[tokio::main]
/// async fn main() { /// async fn main() {
/// let client: Client = Default::default(); // configure your client here /// let base_url = "http://localhost:9000/".parse::<BaseUrl>().unwrap();
/// let static_provider = StaticProvider::new("minioadmin", "minioadmin", None);
/// let client = MinioClient::new(base_url, Some(static_provider), None, None).unwrap();
/// let resp: DeleteBucketLifecycleResponse = client /// let resp: DeleteBucketLifecycleResponse = client
/// .delete_bucket_lifecycle("bucket-name") /// .delete_bucket_lifecycle("bucket-name")
/// .send().await.unwrap(); /// .build().send().await.unwrap();
/// println!("lifecycle of bucket '{}' is deleted", resp.bucket()); /// println!("lifecycle of bucket '{}' is deleted", resp.bucket());
/// } /// }
/// ``` /// ```
pub fn delete_bucket_lifecycle<S: Into<String>>(&self, bucket: S) -> DeleteBucketLifecycle { pub fn delete_bucket_lifecycle<S: Into<String>>(&self, bucket: S) -> DeleteBucketLifecycleBldr {
DeleteBucketLifecycle::new(self.clone(), bucket.into()) DeleteBucketLifecycle::builder()
.client(self.clone())
.bucket(bucket)
} }
} }

View File

@ -13,10 +13,10 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use super::Client; use crate::s3::builders::{DeleteBucketNotification, DeleteBucketNotificationBldr};
use crate::s3::builders::DeleteBucketNotification; use crate::s3::client::MinioClient;
impl Client { impl MinioClient {
/// Creates a [`DeleteBucketNotification`] request builder. /// Creates a [`DeleteBucketNotification`] request builder.
/// ///
/// To execute the request, call [`DeleteBucketNotification::send()`](crate::s3::types::S3Api::send), /// To execute the request, call [`DeleteBucketNotification::send()`](crate::s3::types::S3Api::send),
@ -25,24 +25,30 @@ impl Client {
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// use minio::s3::Client; /// use minio::s3::MinioClient;
/// use minio::s3::creds::StaticProvider;
/// use minio::s3::http::BaseUrl;
/// use minio::s3::response::DeleteBucketNotificationResponse; /// use minio::s3::response::DeleteBucketNotificationResponse;
/// use minio::s3::types::S3Api; /// use minio::s3::types::S3Api;
/// use minio::s3::response::a_response_traits::HasBucket; /// use minio::s3::response::a_response_traits::HasBucket;
/// ///
/// #[tokio::main] /// #[tokio::main]
/// async fn main() { /// async fn main() {
/// let client: Client = Default::default(); // configure your client here /// let base_url = "http://localhost:9000/".parse::<BaseUrl>().unwrap();
/// let static_provider = StaticProvider::new("minioadmin", "minioadmin", None);
/// let client = MinioClient::new(base_url, Some(static_provider), None, None).unwrap();
/// let resp: DeleteBucketNotificationResponse = client /// let resp: DeleteBucketNotificationResponse = client
/// .delete_bucket_notification("bucket-name") /// .delete_bucket_notification("bucket-name")
/// .send().await.unwrap(); /// .build().send().await.unwrap();
/// println!("notification of bucket '{}' is deleted", resp.bucket()); /// println!("notification of bucket '{}' is deleted", resp.bucket());
/// } /// }
/// ``` /// ```
pub fn delete_bucket_notification<S: Into<String>>( pub fn delete_bucket_notification<S: Into<String>>(
&self, &self,
bucket: S, bucket: S,
) -> DeleteBucketNotification { ) -> DeleteBucketNotificationBldr {
DeleteBucketNotification::new(self.clone(), bucket.into()) DeleteBucketNotification::builder()
.client(self.clone())
.bucket(bucket)
} }
} }

View File

@ -13,10 +13,10 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use super::Client; use crate::s3::builders::{DeleteBucketPolicy, DeleteBucketPolicyBldr};
use crate::s3::builders::DeleteBucketPolicy; use crate::s3::client::MinioClient;
impl Client { impl MinioClient {
/// Creates a [`DeleteBucketPolicy`] request builder. /// Creates a [`DeleteBucketPolicy`] request builder.
/// ///
/// To execute the request, call [`DeleteBucketPolicy::send()`](crate::s3::types::S3Api::send), /// To execute the request, call [`DeleteBucketPolicy::send()`](crate::s3::types::S3Api::send),
@ -25,21 +25,27 @@ impl Client {
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// use minio::s3::Client; /// use minio::s3::MinioClient;
/// use minio::s3::creds::StaticProvider;
/// use minio::s3::http::BaseUrl;
/// use minio::s3::response::DeleteBucketPolicyResponse; /// use minio::s3::response::DeleteBucketPolicyResponse;
/// use minio::s3::types::S3Api; /// use minio::s3::types::S3Api;
/// use minio::s3::response::a_response_traits::HasBucket; /// use minio::s3::response::a_response_traits::HasBucket;
/// ///
/// #[tokio::main] /// #[tokio::main]
/// async fn main() { /// async fn main() {
/// let client: Client = Default::default(); // configure your client here /// let base_url = "http://localhost:9000/".parse::<BaseUrl>().unwrap();
/// let static_provider = StaticProvider::new("minioadmin", "minioadmin", None);
/// let client = MinioClient::new(base_url, Some(static_provider), None, None).unwrap();
/// let resp: DeleteBucketPolicyResponse = client /// let resp: DeleteBucketPolicyResponse = client
/// .delete_bucket_policy("bucket-name") /// .delete_bucket_policy("bucket-name")
/// .send().await.unwrap(); /// .build().send().await.unwrap();
/// println!("policy of bucket '{}' is deleted", resp.bucket()); /// println!("policy of bucket '{}' is deleted", resp.bucket());
/// } /// }
/// ``` /// ```
pub fn delete_bucket_policy<S: Into<String>>(&self, bucket: S) -> DeleteBucketPolicy { pub fn delete_bucket_policy<S: Into<String>>(&self, bucket: S) -> DeleteBucketPolicyBldr {
DeleteBucketPolicy::new(self.clone(), bucket.into()) DeleteBucketPolicy::builder()
.client(self.clone())
.bucket(bucket)
} }
} }

View File

@ -13,10 +13,10 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use super::Client; use crate::s3::builders::{DeleteBucketReplication, DeleteBucketReplicationBldr};
use crate::s3::builders::DeleteBucketReplication; use crate::s3::client::MinioClient;
impl Client { impl MinioClient {
/// Creates a [`DeleteBucketReplication`] request builder. /// Creates a [`DeleteBucketReplication`] request builder.
/// ///
/// To execute the request, call [`DeleteBucketReplication::send()`](crate::s3::types::S3Api::send), /// To execute the request, call [`DeleteBucketReplication::send()`](crate::s3::types::S3Api::send),
@ -27,21 +27,30 @@ impl Client {
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// use minio::s3::Client; /// use minio::s3::MinioClient;
/// use minio::s3::creds::StaticProvider;
/// use minio::s3::http::BaseUrl;
/// use minio::s3::response::DeleteBucketReplicationResponse; /// use minio::s3::response::DeleteBucketReplicationResponse;
/// use minio::s3::types::S3Api; /// use minio::s3::types::S3Api;
/// use minio::s3::response::a_response_traits::HasBucket; /// use minio::s3::response::a_response_traits::HasBucket;
/// ///
/// #[tokio::main] /// #[tokio::main]
/// async fn main() { /// async fn main() {
/// let client: Client = Default::default(); // configure your client here /// let base_url = "http://localhost:9000/".parse::<BaseUrl>().unwrap();
/// let static_provider = StaticProvider::new("minioadmin", "minioadmin", None);
/// let client = MinioClient::new(base_url, Some(static_provider), None, None).unwrap();
/// let resp: DeleteBucketReplicationResponse = client /// let resp: DeleteBucketReplicationResponse = client
/// .delete_bucket_replication("bucket-name") /// .delete_bucket_replication("bucket-name")
/// .send().await.unwrap(); /// .build().send().await.unwrap();
/// println!("replication of bucket '{}' is deleted", resp.bucket()); /// println!("replication of bucket '{}' is deleted", resp.bucket());
/// } /// }
/// ``` /// ```
pub fn delete_bucket_replication<S: Into<String>>(&self, bucket: S) -> DeleteBucketReplication { pub fn delete_bucket_replication<S: Into<String>>(
DeleteBucketReplication::new(self.clone(), bucket.into()) &self,
bucket: S,
) -> DeleteBucketReplicationBldr {
DeleteBucketReplication::builder()
.client(self.clone())
.bucket(bucket)
} }
} }

View File

@ -13,10 +13,10 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use super::Client; use crate::s3::builders::{DeleteBucketTagging, DeleteBucketTaggingBldr};
use crate::s3::builders::DeleteBucketTagging; use crate::s3::client::MinioClient;
impl Client { impl MinioClient {
/// Creates a [`DeleteBucketTagging`] request builder. /// Creates a [`DeleteBucketTagging`] request builder.
/// ///
/// To execute the request, call [`DeleteBucketTagging::send()`](crate::s3::types::S3Api::send), /// To execute the request, call [`DeleteBucketTagging::send()`](crate::s3::types::S3Api::send),
@ -27,21 +27,27 @@ impl Client {
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// use minio::s3::Client; /// use minio::s3::MinioClient;
/// use minio::s3::creds::StaticProvider;
/// use minio::s3::http::BaseUrl;
/// use minio::s3::response::DeleteBucketTaggingResponse; /// use minio::s3::response::DeleteBucketTaggingResponse;
/// use minio::s3::types::S3Api; /// use minio::s3::types::S3Api;
/// use minio::s3::response::a_response_traits::HasBucket; /// use minio::s3::response::a_response_traits::HasBucket;
/// ///
/// #[tokio::main] /// #[tokio::main]
/// async fn main() { /// async fn main() {
/// let client: Client = Default::default(); // configure your client here /// let base_url = "http://localhost:9000/".parse::<BaseUrl>().unwrap();
/// let static_provider = StaticProvider::new("minioadmin", "minioadmin", None);
/// let client = MinioClient::new(base_url, Some(static_provider), None, None).unwrap();
/// let resp: DeleteBucketTaggingResponse = client /// let resp: DeleteBucketTaggingResponse = client
/// .delete_bucket_tagging("bucket-name") /// .delete_bucket_tagging("bucket-name")
/// .send().await.unwrap(); /// .build().send().await.unwrap();
/// println!("tags of bucket '{}' are deleted", resp.bucket()); /// println!("tags of bucket '{}' are deleted", resp.bucket());
/// } /// }
/// ``` /// ```
pub fn delete_bucket_tagging<S: Into<String>>(&self, bucket: S) -> DeleteBucketTagging { pub fn delete_bucket_tagging<S: Into<String>>(&self, bucket: S) -> DeleteBucketTaggingBldr {
DeleteBucketTagging::new(self.clone(), bucket.into()) DeleteBucketTagging::builder()
.client(self.clone())
.bucket(bucket)
} }
} }

View File

@ -13,10 +13,10 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use super::Client; use crate::s3::builders::{DeleteObjectLockConfig, DeleteObjectLockConfigBldr};
use crate::s3::builders::DeleteObjectLockConfig; use crate::s3::client::MinioClient;
impl Client { impl MinioClient {
/// Creates a [`DeleteObjectLockConfig`] request builder. /// Creates a [`DeleteObjectLockConfig`] request builder.
/// ///
/// To execute the request, call [`DeleteObjectLockConfig::send()`](crate::s3::types::S3Api::send), /// To execute the request, call [`DeleteObjectLockConfig::send()`](crate::s3::types::S3Api::send),
@ -27,34 +27,46 @@ impl Client {
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// use minio::s3::Client; /// use minio::s3::MinioClient;
/// use minio::s3::creds::StaticProvider;
/// use minio::s3::http::BaseUrl;
/// use minio::s3::response::{DeleteObjectLockConfigResponse, CreateBucketResponse, PutObjectLockConfigResponse}; /// use minio::s3::response::{DeleteObjectLockConfigResponse, CreateBucketResponse, PutObjectLockConfigResponse};
/// use minio::s3::types::{S3Api, ObjectLockConfig, RetentionMode}; /// use minio::s3::types::{S3Api, ObjectLockConfig, RetentionMode};
/// use minio::s3::response::a_response_traits::HasBucket; /// use minio::s3::response::a_response_traits::HasBucket;
/// ///
/// #[tokio::main] /// #[tokio::main]
/// async fn main() { /// async fn main() {
/// let client: Client = Default::default(); // configure your client here /// let base_url = "http://localhost:9000/".parse::<BaseUrl>().unwrap();
/// let static_provider = StaticProvider::new("minioadmin", "minioadmin", None);
/// let client = MinioClient::new(base_url, Some(static_provider), None, None).unwrap();
/// let bucket_name = "bucket-name"; /// let bucket_name = "bucket-name";
/// ///
/// let resp: CreateBucketResponse = /// let resp: CreateBucketResponse = client
/// client.create_bucket(bucket_name).object_lock(true).send().await.unwrap(); /// .create_bucket(bucket_name).object_lock(true)
/// .build().send().await.unwrap();
/// println!("created bucket '{}' with object locking enabled", resp.bucket()); /// println!("created bucket '{}' with object locking enabled", resp.bucket());
/// ///
/// ///
/// const DURATION_DAYS: i32 = 7; /// const DURATION_DAYS: i32 = 7;
/// let config = ObjectLockConfig::new(RetentionMode::GOVERNANCE, Some(DURATION_DAYS), None).unwrap(); /// let config = ObjectLockConfig::new(RetentionMode::GOVERNANCE, Some(DURATION_DAYS), None).unwrap();
/// ///
/// let resp: PutObjectLockConfigResponse = /// let resp: PutObjectLockConfigResponse = client
/// client.put_object_lock_config(bucket_name).config(config).send().await.unwrap(); /// .put_object_lock_config(bucket_name).config(config)
/// .build().send().await.unwrap();
/// println!("configured object locking for bucket '{}'", resp.bucket()); /// println!("configured object locking for bucket '{}'", resp.bucket());
/// ///
/// let resp: DeleteObjectLockConfigResponse = /// let resp: DeleteObjectLockConfigResponse = client
/// client.delete_object_lock_config(bucket_name).send().await.unwrap(); /// .delete_object_lock_config(bucket_name)
/// .build().send().await.unwrap();
/// println!("object locking of bucket '{}' is deleted", resp.bucket()); /// println!("object locking of bucket '{}' is deleted", resp.bucket());
/// } /// }
/// ``` /// ```
pub fn delete_object_lock_config<S: Into<String>>(&self, bucket: S) -> DeleteObjectLockConfig { pub fn delete_object_lock_config<S: Into<String>>(
DeleteObjectLockConfig::new(self.clone(), bucket.into()) &self,
bucket: S,
) -> DeleteObjectLockConfigBldr {
DeleteObjectLockConfig::builder()
.client(self.clone())
.bucket(bucket)
} }
} }

View File

@ -13,10 +13,10 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use super::Client; use crate::s3::builders::{DeleteObjectTagging, DeleteObjectTaggingBldr};
use crate::s3::builders::DeleteObjectTagging; use crate::s3::client::MinioClient;
impl Client { impl MinioClient {
/// Creates a [`DeleteObjectTagging`] request builder. /// Creates a [`DeleteObjectTagging`] request builder.
/// ///
/// To execute the request, call [`DeleteObjectTagging::send()`](crate::s3::types::S3Api::send), /// To execute the request, call [`DeleteObjectTagging::send()`](crate::s3::types::S3Api::send),
@ -27,17 +27,21 @@ impl Client {
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// use minio::s3::Client; /// use minio::s3::MinioClient;
/// use minio::s3::creds::StaticProvider;
/// use minio::s3::http::BaseUrl;
/// use minio::s3::response::DeleteObjectTaggingResponse; /// use minio::s3::response::DeleteObjectTaggingResponse;
/// use minio::s3::types::S3Api; /// use minio::s3::types::S3Api;
/// use minio::s3::response::a_response_traits::{HasBucket, HasObject}; /// use minio::s3::response::a_response_traits::{HasBucket, HasObject};
/// ///
/// #[tokio::main] /// #[tokio::main]
/// async fn main() { /// async fn main() {
/// let client: Client = Default::default(); // configure your client here /// let base_url = "http://localhost:9000/".parse::<BaseUrl>().unwrap();
/// let static_provider = StaticProvider::new("minioadmin", "minioadmin", None);
/// let client = MinioClient::new(base_url, Some(static_provider), None, None).unwrap();
/// let resp: DeleteObjectTaggingResponse = client /// let resp: DeleteObjectTaggingResponse = client
/// .delete_object_tagging("bucket-name", "object_name") /// .delete_object_tagging("bucket-name", "object_name")
/// .send().await.unwrap(); /// .build().send().await.unwrap();
/// println!("legal hold of object '{}' in bucket '{}' is deleted", resp.object(), resp.bucket()); /// println!("legal hold of object '{}' in bucket '{}' is deleted", resp.object(), resp.bucket());
/// } /// }
/// ``` /// ```
@ -45,7 +49,10 @@ impl Client {
&self, &self,
bucket: S1, bucket: S1,
object: S2, object: S2,
) -> DeleteObjectTagging { ) -> DeleteObjectTaggingBldr {
DeleteObjectTagging::new(self.clone(), bucket.into(), object.into()) DeleteObjectTagging::builder()
.client(self.clone())
.bucket(bucket)
.object(object)
} }
} }

View File

@ -13,14 +13,13 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::s3::{ use crate::s3::builders::{
builders::{ DeleteObject, DeleteObjectBldr, DeleteObjects, DeleteObjectsBldr, DeleteObjectsStreaming,
DeleteObject, DeleteObjects, DeleteObjectsStreaming, ObjectToDelete, ObjectsStream, ObjectToDelete, ObjectsStream,
},
client::Client,
}; };
use crate::s3::client::MinioClient;
impl Client { impl MinioClient {
/// Creates a [`DeleteObject`] request builder to delete a single object from an S3 bucket. /// Creates a [`DeleteObject`] request builder to delete a single object from an S3 bucket.
/// ///
/// To execute the request, call [`DeleteObject::send()`](crate::s3::types::S3Api::send), /// To execute the request, call [`DeleteObject::send()`](crate::s3::types::S3Api::send),
@ -29,7 +28,9 @@ impl Client {
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// use minio::s3::Client; /// use minio::s3::MinioClient;
/// use minio::s3::creds::StaticProvider;
/// use minio::s3::http::BaseUrl;
/// use minio::s3::response::DeleteObjectResponse; /// use minio::s3::response::DeleteObjectResponse;
/// use minio::s3::builders::ObjectToDelete; /// use minio::s3::builders::ObjectToDelete;
/// use minio::s3::types::S3Api; /// use minio::s3::types::S3Api;
@ -37,10 +38,12 @@ impl Client {
/// ///
/// #[tokio::main] /// #[tokio::main]
/// async fn main() { /// async fn main() {
/// let client: Client = Default::default(); // configure your client here /// let base_url = "http://localhost:9000/".parse::<BaseUrl>().unwrap();
/// let static_provider = StaticProvider::new("minioadmin", "minioadmin", None);
/// let client = MinioClient::new(base_url, Some(static_provider), None, None).unwrap();
/// let resp: DeleteObjectResponse = client /// let resp: DeleteObjectResponse = client
/// .delete_object("bucket-name", ObjectToDelete::from("object-name")) /// .delete_object("bucket-name", ObjectToDelete::from("object-name"))
/// .send().await.unwrap(); /// .build().send().await.unwrap();
/// println!("the object is deleted. The delete marker has version '{:?}'", resp.version_id()); /// println!("the object is deleted. The delete marker has version '{:?}'", resp.version_id());
/// } /// }
/// ``` /// ```
@ -48,20 +51,26 @@ impl Client {
&self, &self,
bucket: S, bucket: S,
object: D, object: D,
) -> DeleteObject { ) -> DeleteObjectBldr {
DeleteObject::new(self.clone(), bucket.into(), object) DeleteObject::builder()
.client(self.clone())
.bucket(bucket)
.object(object)
} }
/// Creates a [`DeleteObjects`] request builder to delete multiple objects from an S3 bucket. /// Creates a [`DeleteObjects`] request builder to delete multiple objects from an S3 bucket.
/// ///
/// To execute the request, call [`DeleteObjects::send()`](crate::s3::types::S3Api::send), /// To execute the request, call [`DeleteObjects::send()`](crate::s3::types::S3Api::send),
/// which returns a [`Result`] containing a [`DeleteObjectsResponse`](crate::s3::response::DeleteObjectsResponse). /// which returns a [`Result`] containing a [`DeleteObjectsResponse`](crate::s3::response::DeleteObjectsResponse).
pub fn delete_objects<S: Into<String>, D: Into<ObjectToDelete>>( pub fn delete_objects<S: Into<String>>(
&self, &self,
bucket: S, bucket: S,
object: Vec<ObjectToDelete>, objects: Vec<ObjectToDelete>,
) -> DeleteObjects { ) -> DeleteObjectsBldr {
DeleteObjects::new(self.clone(), bucket.into(), object) DeleteObjects::builder()
.client(self.clone())
.bucket(bucket)
.objects(objects)
} }
/// Creates a [`DeleteObjectsStreaming`] request builder to delete a stream of objects from an S3 bucket. /// Creates a [`DeleteObjectsStreaming`] request builder to delete a stream of objects from an S3 bucket.

View File

@ -13,10 +13,10 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use super::Client; use crate::s3::builders::{GetBucketEncryption, GetBucketEncryptionBldr};
use crate::s3::builders::GetBucketEncryption; use crate::s3::client::MinioClient;
impl Client { impl MinioClient {
/// Creates a [`GetBucketEncryption`] request builder. /// Creates a [`GetBucketEncryption`] request builder.
/// ///
/// To execute the request, call [`GetBucketEncryption::send()`](crate::s3::types::S3Api::send), /// To execute the request, call [`GetBucketEncryption::send()`](crate::s3::types::S3Api::send),
@ -25,21 +25,27 @@ impl Client {
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// use minio::s3::Client; /// use minio::s3::MinioClient;
/// use minio::s3::creds::StaticProvider;
/// use minio::s3::http::BaseUrl;
/// use minio::s3::response::GetBucketEncryptionResponse; /// use minio::s3::response::GetBucketEncryptionResponse;
/// use minio::s3::types::S3Api; /// use minio::s3::types::S3Api;
/// use minio::s3::response::a_response_traits::HasBucket; /// use minio::s3::response::a_response_traits::HasBucket;
/// ///
/// #[tokio::main] /// #[tokio::main]
/// async fn main() { /// async fn main() {
/// let client: Client = Default::default(); // configure your client here /// let base_url = "http://localhost:9000/".parse::<BaseUrl>().unwrap();
/// let static_provider = StaticProvider::new("minioadmin", "minioadmin", None);
/// let client = MinioClient::new(base_url, Some(static_provider), None, None).unwrap();
/// let resp: GetBucketEncryptionResponse = client /// let resp: GetBucketEncryptionResponse = client
/// .get_bucket_encryption("bucket-name") /// .get_bucket_encryption("bucket-name")
/// .send().await.unwrap(); /// .build().send().await.unwrap();
/// println!("retrieved SseConfig '{:?}' from bucket '{}'", resp.config(), resp.bucket()); /// println!("retrieved SseConfig '{:?}' from bucket '{}'", resp.config(), resp.bucket());
/// } /// }
/// ``` /// ```
pub fn get_bucket_encryption<S: Into<String>>(&self, bucket: S) -> GetBucketEncryption { pub fn get_bucket_encryption<S: Into<String>>(&self, bucket: S) -> GetBucketEncryptionBldr {
GetBucketEncryption::new(self.clone(), bucket.into()) GetBucketEncryption::builder()
.client(self.clone())
.bucket(bucket)
} }
} }

View File

@ -13,10 +13,10 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use super::Client; use crate::s3::builders::{GetBucketLifecycle, GetBucketLifecycleBldr};
use crate::s3::builders::GetBucketLifecycle; use crate::s3::client::MinioClient;
impl Client { impl MinioClient {
/// Creates a [`GetBucketLifecycle`] request builder. /// Creates a [`GetBucketLifecycle`] request builder.
/// ///
/// To execute the request, call [`GetBucketLifecycle::send()`](crate::s3::types::S3Api::send), /// To execute the request, call [`GetBucketLifecycle::send()`](crate::s3::types::S3Api::send),
@ -25,21 +25,27 @@ impl Client {
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// use minio::s3::Client; /// use minio::s3::MinioClient;
/// use minio::s3::creds::StaticProvider;
/// use minio::s3::http::BaseUrl;
/// use minio::s3::response::GetBucketLifecycleResponse; /// use minio::s3::response::GetBucketLifecycleResponse;
/// use minio::s3::types::S3Api; /// use minio::s3::types::S3Api;
/// use minio::s3::response::a_response_traits::HasBucket; /// use minio::s3::response::a_response_traits::HasBucket;
/// ///
/// #[tokio::main] /// #[tokio::main]
/// async fn main() { /// async fn main() {
/// let client: Client = Default::default(); // configure your client here /// let base_url = "http://localhost:9000/".parse::<BaseUrl>().unwrap();
/// let static_provider = StaticProvider::new("minioadmin", "minioadmin", None);
/// let client = MinioClient::new(base_url, Some(static_provider), None, None).unwrap();
/// let resp: GetBucketLifecycleResponse = client /// let resp: GetBucketLifecycleResponse = client
/// .get_bucket_lifecycle("bucket-name") /// .get_bucket_lifecycle("bucket-name")
/// .send().await.unwrap(); /// .build().send().await.unwrap();
/// println!("retrieved bucket lifecycle config '{:?}' from bucket '{}'", resp.config(), resp.bucket()); /// println!("retrieved bucket lifecycle config '{:?}' from bucket '{}'", resp.config(), resp.bucket());
/// } /// }
/// ``` /// ```
pub fn get_bucket_lifecycle<S: Into<String>>(&self, bucket: S) -> GetBucketLifecycle { pub fn get_bucket_lifecycle<S: Into<String>>(&self, bucket: S) -> GetBucketLifecycleBldr {
GetBucketLifecycle::new(self.clone(), bucket.into()) GetBucketLifecycle::builder()
.client(self.clone())
.bucket(bucket)
} }
} }

View File

@ -13,10 +13,10 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use super::Client; use crate::s3::builders::{GetBucketNotification, GetBucketNotificationBldr};
use crate::s3::builders::GetBucketNotification; use crate::s3::client::MinioClient;
impl Client { impl MinioClient {
/// Creates a [`GetBucketNotification`] request builder. /// Creates a [`GetBucketNotification`] request builder.
/// ///
/// To execute the request, call [`GetBucketNotification::send()`](crate::s3::types::S3Api::send), /// To execute the request, call [`GetBucketNotification::send()`](crate::s3::types::S3Api::send),
@ -25,21 +25,27 @@ impl Client {
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// use minio::s3::Client; /// use minio::s3::MinioClient;
/// use minio::s3::creds::StaticProvider;
/// use minio::s3::http::BaseUrl;
/// use minio::s3::response::GetBucketNotificationResponse; /// use minio::s3::response::GetBucketNotificationResponse;
/// use minio::s3::types::S3Api; /// use minio::s3::types::S3Api;
/// use minio::s3::response::a_response_traits::HasBucket; /// use minio::s3::response::a_response_traits::HasBucket;
/// ///
/// #[tokio::main] /// #[tokio::main]
/// async fn main() { /// async fn main() {
/// let client: Client = Default::default(); // configure your client here /// let base_url = "http://localhost:9000/".parse::<BaseUrl>().unwrap();
/// let static_provider = StaticProvider::new("minioadmin", "minioadmin", None);
/// let client = MinioClient::new(base_url, Some(static_provider), None, None).unwrap();
/// let resp: GetBucketNotificationResponse = client /// let resp: GetBucketNotificationResponse = client
/// .get_bucket_notification("bucket-name") /// .get_bucket_notification("bucket-name")
/// .send().await.unwrap(); /// .build().send().await.unwrap();
/// println!("retrieved bucket notification config '{:?}' from bucket '{}'", resp.config(), resp.bucket()); /// println!("retrieved bucket notification config '{:?}' from bucket '{}'", resp.config(), resp.bucket());
/// } /// }
/// ``` /// ```
pub fn get_bucket_notification<S: Into<String>>(&self, bucket: S) -> GetBucketNotification { pub fn get_bucket_notification<S: Into<String>>(&self, bucket: S) -> GetBucketNotificationBldr {
GetBucketNotification::new(self.clone(), bucket.into()) GetBucketNotification::builder()
.client(self.clone())
.bucket(bucket)
} }
} }

View File

@ -13,10 +13,10 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use super::Client; use crate::s3::builders::{GetBucketPolicy, GetBucketPolicyBldr};
use crate::s3::builders::GetBucketPolicy; use crate::s3::client::MinioClient;
impl Client { impl MinioClient {
/// Creates a [`GetBucketPolicy`] request builder. /// Creates a [`GetBucketPolicy`] request builder.
/// ///
/// To execute the request, call [`GetBucketPolicy::send()`](crate::s3::types::S3Api::send), /// To execute the request, call [`GetBucketPolicy::send()`](crate::s3::types::S3Api::send),
@ -25,21 +25,27 @@ impl Client {
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// use minio::s3::Client; /// use minio::s3::MinioClient;
/// use minio::s3::creds::StaticProvider;
/// use minio::s3::http::BaseUrl;
/// use minio::s3::response::GetBucketPolicyResponse; /// use minio::s3::response::GetBucketPolicyResponse;
/// use minio::s3::types::S3Api; /// use minio::s3::types::S3Api;
/// use minio::s3::response::a_response_traits::HasBucket; /// use minio::s3::response::a_response_traits::HasBucket;
/// ///
/// #[tokio::main] /// #[tokio::main]
/// async fn main() { /// async fn main() {
/// let client: Client = Default::default(); // configure your client here /// let base_url = "http://localhost:9000/".parse::<BaseUrl>().unwrap();
/// let static_provider = StaticProvider::new("minioadmin", "minioadmin", None);
/// let client = MinioClient::new(base_url, Some(static_provider), None, None).unwrap();
/// let resp: GetBucketPolicyResponse = client /// let resp: GetBucketPolicyResponse = client
/// .get_bucket_policy("bucket-name") /// .get_bucket_policy("bucket-name")
/// .send().await.unwrap(); /// .build().send().await.unwrap();
/// println!("retrieved bucket policy config '{:?}' from bucket '{}'", resp.config(), resp.bucket()); /// println!("retrieved bucket policy config '{:?}' from bucket '{}'", resp.config(), resp.bucket());
/// } /// }
/// ``` /// ```
pub fn get_bucket_policy<S: Into<String>>(&self, bucket: S) -> GetBucketPolicy { pub fn get_bucket_policy<S: Into<String>>(&self, bucket: S) -> GetBucketPolicyBldr {
GetBucketPolicy::new(self.clone(), bucket.into()) GetBucketPolicy::builder()
.client(self.clone())
.bucket(bucket)
} }
} }

View File

@ -13,10 +13,10 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use super::Client; use crate::s3::builders::{GetBucketReplication, GetBucketReplicationBldr};
use crate::s3::builders::GetBucketReplication; use crate::s3::client::MinioClient;
impl Client { impl MinioClient {
/// Creates a [`GetBucketReplication`] request builder. /// Creates a [`GetBucketReplication`] request builder.
/// ///
/// To execute the request, call [`GetBucketReplication::send()`](crate::s3::types::S3Api::send), /// To execute the request, call [`GetBucketReplication::send()`](crate::s3::types::S3Api::send),
@ -27,21 +27,27 @@ impl Client {
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// use minio::s3::Client; /// use minio::s3::MinioClient;
/// use minio::s3::creds::StaticProvider;
/// use minio::s3::http::BaseUrl;
/// use minio::s3::response::GetBucketReplicationResponse; /// use minio::s3::response::GetBucketReplicationResponse;
/// use minio::s3::types::S3Api; /// use minio::s3::types::S3Api;
/// use minio::s3::response::a_response_traits::HasBucket; /// use minio::s3::response::a_response_traits::HasBucket;
/// ///
/// #[tokio::main] /// #[tokio::main]
/// async fn main() { /// async fn main() {
/// let client: Client = Default::default(); // configure your client here /// let base_url = "http://localhost:9000/".parse::<BaseUrl>().unwrap();
/// let static_provider = StaticProvider::new("minioadmin", "minioadmin", None);
/// let client = MinioClient::new(base_url, Some(static_provider), None, None).unwrap();
/// let resp: GetBucketReplicationResponse = client /// let resp: GetBucketReplicationResponse = client
/// .get_bucket_replication("bucket-name") /// .get_bucket_replication("bucket-name")
/// .send().await.unwrap(); /// .build().send().await.unwrap();
/// println!("retrieved bucket replication config '{:?}' from bucket '{}'", resp.config(), resp.bucket()); /// println!("retrieved bucket replication config '{:?}' from bucket '{}'", resp.config(), resp.bucket());
/// } /// }
/// ``` /// ```
pub fn get_bucket_replication<S: Into<String>>(&self, bucket: S) -> GetBucketReplication { pub fn get_bucket_replication<S: Into<String>>(&self, bucket: S) -> GetBucketReplicationBldr {
GetBucketReplication::new(self.clone(), bucket.into()) GetBucketReplication::builder()
.client(self.clone())
.bucket(bucket)
} }
} }

Some files were not shown because too many files have changed in this diff Show More