diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index bab1690..4b4f61f 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -19,11 +19,12 @@ jobs: - uses: actions/checkout@v4 - name: Build run: | + cargo --version cargo fmt --all -- --check cargo clippy --all-targets --all-features cargo build --bins --examples --tests --benches --verbose - - name: Run tests S3 + - name: Run tests run: | ./tests/start-server.sh export SERVER_ENDPOINT=localhost:9000 diff --git a/benches/s3/api_benchmarks.rs b/benches/s3/api_benchmarks.rs index e105da4..8f1aed3 100644 --- a/benches/s3/api_benchmarks.rs +++ b/benches/s3/api_benchmarks.rs @@ -18,7 +18,7 @@ mod bench_bucket_lifecycle; mod bench_bucket_notification; mod bench_bucket_policy; mod bench_bucket_replication; -mod bench_bucket_tags; +mod bench_bucket_tagging; mod bench_bucket_versioning; mod bench_list_bucket; mod bench_object_append; @@ -27,7 +27,7 @@ mod bench_object_legal_hold; mod bench_object_lock_config; mod bench_object_put; mod bench_object_retention; -mod bench_object_tags; +mod bench_object_tagging; mod common_benches; use criterion::{Criterion, criterion_group, criterion_main}; @@ -40,7 +40,7 @@ use crate::bench_bucket_notification::*; use crate::bench_bucket_policy::*; #[allow(unused_imports)] use crate::bench_bucket_replication::*; -use crate::bench_bucket_tags::*; +use crate::bench_bucket_tagging::*; use crate::bench_bucket_versioning::*; use crate::bench_list_bucket::*; #[allow(unused_imports)] @@ -51,7 +51,7 @@ use crate::bench_object_legal_hold::*; use crate::bench_object_lock_config::*; use crate::bench_object_put::bench_object_put; use crate::bench_object_retention::*; -use crate::bench_object_tags::*; +use crate::bench_object_tagging::*; criterion_group!( name = benches; @@ -63,27 +63,27 @@ criterion_group!( .measurement_time(Duration::from_secs_f32(10.0)); targets = bench_bucket_exists, - bench_set_bucket_lifecycle, + bench_put_bucket_lifecycle, bench_get_bucket_lifecycle, bench_delete_bucket_lifecycle, // - //bench_set_bucket_notification, //A specified destination ARN does not exist or is not well-formed + //bench_put_bucket_notification, //A specified destination ARN does not exist or is not well-formed //bench_get_bucket_notification, //bench_delete_bucket_notification, // - bench_set_bucket_policy, + bench_put_bucket_policy, bench_get_bucket_policy, bench_delete_bucket_policy, // - //bench_set_bucket_replication, //TODO setup permissions to allow replication + //bench_put_bucket_replication, //TODO setup permissions to allow replication //bench_get_bucket_replication, //bench_delete_bucket_replication, // - bench_set_bucket_tags, - bench_get_bucket_tags, - bench_delete_bucket_tags, + bench_put_bucket_tagging, + bench_get_bucket_tagging, + bench_delete_bucket_tagging, // - bench_set_bucket_versioning, + bench_put_bucket_versioning, bench_get_bucket_versioning, // bench_list_buckets, @@ -91,19 +91,18 @@ criterion_group!( bench_object_append, bench_object_put, // - bench_enable_object_legal_hold, - bench_disable_object_legal_hold, - bench_is_object_legal_hold, + bench_put_object_legal_hold, + bench_get_object_legal_hold, // - bench_set_object_lock_config, + bench_put_object_lock_config, bench_get_object_lock_config, bench_delete_object_lock_config, // - bench_set_object_retention, + bench_put_object_retention, bench_get_object_retention, // - bench_set_object_tags, - bench_get_object_tags + bench_put_object_tagging, + bench_get_object_tagging ); criterion_main!(benches); diff --git a/benches/s3/bench_bucket_lifecycle.rs b/benches/s3/bench_bucket_lifecycle.rs index ab9ce9d..56bfb67 100644 --- a/benches/s3/bench_bucket_lifecycle.rs +++ b/benches/s3/bench_bucket_lifecycle.rs @@ -16,18 +16,18 @@ use crate::common_benches::{Ctx2, benchmark_s3_api}; use criterion::Criterion; -use minio::s3::builders::{DeleteBucketLifecycle, GetBucketLifecycle, SetBucketLifecycle}; +use minio::s3::builders::{DeleteBucketLifecycle, GetBucketLifecycle, PutBucketLifecycle}; use minio::s3::types::S3Api; use minio_common::example::create_bucket_lifecycle_config_examples; -pub(crate) fn bench_set_bucket_lifecycle(criterion: &mut Criterion) { +pub(crate) fn bench_put_bucket_lifecycle(criterion: &mut Criterion) { benchmark_s3_api( - "set_bucket_lifecycle", + "put_bucket_lifecycle", criterion, || async { Ctx2::new().await }, |ctx| { let config = create_bucket_lifecycle_config_examples(); - SetBucketLifecycle::new(ctx.client.clone(), ctx.bucket.clone()) + PutBucketLifecycle::new(ctx.client.clone(), ctx.bucket.clone()) .life_cycle_config(config) }, ) @@ -40,7 +40,7 @@ pub(crate) fn bench_get_bucket_lifecycle(criterion: &mut Criterion) { let ctx = Ctx2::new().await; let config = create_bucket_lifecycle_config_examples(); ctx.client - .set_bucket_lifecycle(&ctx.bucket) + .put_bucket_lifecycle(&ctx.bucket) .life_cycle_config(config) .send() .await diff --git a/benches/s3/bench_bucket_notification.rs b/benches/s3/bench_bucket_notification.rs index 71c9a7e..56da151 100644 --- a/benches/s3/bench_bucket_notification.rs +++ b/benches/s3/bench_bucket_notification.rs @@ -16,19 +16,19 @@ use crate::common_benches::{Ctx2, benchmark_s3_api}; use criterion::Criterion; -use minio::s3::builders::{DeleteBucketNotification, GetBucketNotification, SetBucketNotification}; +use minio::s3::builders::{DeleteBucketNotification, GetBucketNotification, PutBucketNotification}; use minio::s3::types::S3Api; use minio_common::example::create_bucket_notification_config_example; #[allow(dead_code)] -pub(crate) fn bench_set_bucket_notification(criterion: &mut Criterion) { +pub(crate) fn bench_put_bucket_notification(criterion: &mut Criterion) { benchmark_s3_api( - "set_bucket_notification", + "put_bucket_notification", criterion, || async { Ctx2::new().await }, |ctx| { let config = create_bucket_notification_config_example(); - SetBucketNotification::new(ctx.client.clone(), ctx.bucket.clone()) + PutBucketNotification::new(ctx.client.clone(), ctx.bucket.clone()) .notification_config(config) }, ) @@ -42,7 +42,7 @@ pub(crate) fn bench_get_bucket_notification(criterion: &mut Criterion) { let ctx = Ctx2::new().await; let config = create_bucket_notification_config_example(); ctx.client - .set_bucket_notification(&ctx.bucket) + .put_bucket_notification(&ctx.bucket) .notification_config(config) .send() .await diff --git a/benches/s3/bench_bucket_policy.rs b/benches/s3/bench_bucket_policy.rs index b6c89e0..d63a913 100644 --- a/benches/s3/bench_bucket_policy.rs +++ b/benches/s3/bench_bucket_policy.rs @@ -16,18 +16,18 @@ use crate::common_benches::{Ctx2, benchmark_s3_api}; use criterion::Criterion; -use minio::s3::builders::{DeleteBucketPolicy, GetBucketPolicy, SetBucketPolicy}; +use minio::s3::builders::{DeleteBucketPolicy, GetBucketPolicy, PutBucketPolicy}; use minio::s3::types::S3Api; use minio_common::example::create_bucket_policy_config_example; -pub(crate) fn bench_set_bucket_policy(criterion: &mut Criterion) { +pub(crate) fn bench_put_bucket_policy(criterion: &mut Criterion) { benchmark_s3_api( - "set_bucket_policy", + "put_bucket_policy", criterion, || async { Ctx2::new().await }, |ctx| { let config = create_bucket_policy_config_example(&ctx.bucket); - SetBucketPolicy::new(ctx.client.clone(), ctx.bucket.clone()).config(config) + PutBucketPolicy::new(ctx.client.clone(), ctx.bucket.clone()).config(config) }, ) } @@ -38,7 +38,7 @@ pub(crate) fn bench_get_bucket_policy(criterion: &mut Criterion) { || async { let ctx = Ctx2::new().await; let config = create_bucket_policy_config_example(&ctx.bucket); - SetBucketPolicy::new(ctx.client.clone(), ctx.bucket.clone()) + PutBucketPolicy::new(ctx.client.clone(), ctx.bucket.clone()) .config(config) .send() .await diff --git a/benches/s3/bench_bucket_replication.rs b/benches/s3/bench_bucket_replication.rs index e877c1c..e07a917 100644 --- a/benches/s3/bench_bucket_replication.rs +++ b/benches/s3/bench_bucket_replication.rs @@ -17,32 +17,32 @@ use crate::common_benches::{Ctx2, benchmark_s3_api}; use criterion::Criterion; use minio::s3::builders::{ - DeleteBucketReplication, GetBucketReplication, SetBucketReplication, VersioningStatus, + DeleteBucketReplication, GetBucketReplication, PutBucketReplication, VersioningStatus, }; -use minio::s3::response::SetBucketVersioningResponse; +use minio::s3::response::PutBucketVersioningResponse; use minio::s3::types::S3Api; use minio_common::example::create_bucket_replication_config_example; #[allow(dead_code)] -pub(crate) fn bench_set_bucket_replication(criterion: &mut Criterion) { +pub(crate) fn bench_put_bucket_replication(criterion: &mut Criterion) { benchmark_s3_api( - "set_bucket_replication", + "put_bucket_replication", criterion, || async { let mut ctx = Ctx2::new().await; ctx.new_aux().await; - let _resp: SetBucketVersioningResponse = ctx + let _resp: PutBucketVersioningResponse = ctx .client - .set_bucket_versioning(&ctx.bucket) + .put_bucket_versioning(&ctx.bucket) .versioning_status(VersioningStatus::Enabled) .send() .await .unwrap(); - let _resp: SetBucketVersioningResponse = ctx + let _resp: PutBucketVersioningResponse = ctx .client - .set_bucket_versioning(&ctx.aux_bucket.clone().unwrap()) + .put_bucket_versioning(&ctx.aux_bucket.clone().unwrap()) .versioning_status(VersioningStatus::Enabled) .send() .await @@ -53,7 +53,7 @@ pub(crate) fn bench_set_bucket_replication(criterion: &mut Criterion) { |ctx| { let config = create_bucket_replication_config_example(ctx.aux_bucket.clone().unwrap().as_str()); - SetBucketReplication::new(ctx.client.clone(), ctx.bucket.clone()) + PutBucketReplication::new(ctx.client.clone(), ctx.bucket.clone()) .replication_config(config) }, ) @@ -67,17 +67,17 @@ pub(crate) fn bench_get_bucket_replication(criterion: &mut Criterion) { let mut ctx = Ctx2::new().await; ctx.new_aux().await; - let _resp: SetBucketVersioningResponse = ctx + let _resp: PutBucketVersioningResponse = ctx .client - .set_bucket_versioning(&ctx.bucket) + .put_bucket_versioning(&ctx.bucket) .versioning_status(VersioningStatus::Enabled) .send() .await .unwrap(); - let _resp: SetBucketVersioningResponse = ctx + let _resp: PutBucketVersioningResponse = ctx .client - .set_bucket_versioning(&ctx.aux_bucket.clone().unwrap()) + .put_bucket_versioning(&ctx.aux_bucket.clone().unwrap()) .versioning_status(VersioningStatus::Enabled) .send() .await @@ -97,17 +97,17 @@ pub(crate) fn bench_delete_bucket_replication(criterion: &mut Criterion) { let mut ctx = Ctx2::new().await; ctx.new_aux().await; - let _resp: SetBucketVersioningResponse = ctx + let _resp: PutBucketVersioningResponse = ctx .client - .set_bucket_versioning(&ctx.bucket) + .put_bucket_versioning(&ctx.bucket) .versioning_status(VersioningStatus::Enabled) .send() .await .unwrap(); - let _resp: SetBucketVersioningResponse = ctx + let _resp: PutBucketVersioningResponse = ctx .client - .set_bucket_versioning(&ctx.aux_bucket.clone().unwrap()) + .put_bucket_versioning(&ctx.aux_bucket.clone().unwrap()) .versioning_status(VersioningStatus::Enabled) .send() .await diff --git a/benches/s3/bench_bucket_tags.rs b/benches/s3/bench_bucket_tagging.rs similarity index 61% rename from benches/s3/bench_bucket_tags.rs rename to benches/s3/bench_bucket_tagging.rs index 9237a27..d18437c 100644 --- a/benches/s3/bench_bucket_tags.rs +++ b/benches/s3/bench_bucket_tagging.rs @@ -16,51 +16,52 @@ use crate::common_benches::{Ctx2, benchmark_s3_api, skip_express_mode}; use criterion::Criterion; -use minio::s3::builders::{DeleteBucketTags, GetBucketTags, SetBucketTags}; +use minio::s3::builders::{DeleteBucketTagging, GetBucketTagging, PutBucketTagging}; use minio::s3::types::S3Api; use minio_common::example::create_tags_example; -pub(crate) fn bench_set_bucket_tags(criterion: &mut Criterion) { - if skip_express_mode("bench_set_bucket_tags") { +pub(crate) fn bench_put_bucket_tagging(criterion: &mut Criterion) { + if skip_express_mode("bench_put_bucket_tagging") { return; } benchmark_s3_api( - "set_bucket_tags", + "put_bucket_tagging", criterion, || async { Ctx2::new().await }, |ctx| { - SetBucketTags::new(ctx.client.clone(), ctx.bucket.clone()).tags(create_tags_example()) + PutBucketTagging::new(ctx.client.clone(), ctx.bucket.clone()) + .tags(create_tags_example()) }, ) } -pub(crate) fn bench_get_bucket_tags(criterion: &mut Criterion) { - if skip_express_mode("bench_get_bucket_tags") { +pub(crate) fn bench_get_bucket_tagging(criterion: &mut Criterion) { + if skip_express_mode("bench_get_bucket_tagging") { return; } benchmark_s3_api( - "get_bucket_tags", + "get_bucket_tagging", criterion, || async { let ctx = Ctx2::new().await; ctx.client - .set_bucket_tags(&ctx.bucket) + .put_bucket_tagging(&ctx.bucket) .tags(create_tags_example()) .send() .await .unwrap(); ctx }, - |ctx| GetBucketTags::new(ctx.client.clone(), ctx.bucket.clone()), + |ctx| GetBucketTagging::new(ctx.client.clone(), ctx.bucket.clone()), ) } -pub(crate) fn bench_delete_bucket_tags(criterion: &mut Criterion) { - if skip_express_mode("bench_delete_bucket_tags") { +pub(crate) fn bench_delete_bucket_tagging(criterion: &mut Criterion) { + if skip_express_mode("bench_delete_bucket_tagging") { return; } benchmark_s3_api( - "delete_bucket_tags", + "delete_bucket_tagging", criterion, || async { Ctx2::new().await }, - |ctx| DeleteBucketTags::new(ctx.client.clone(), ctx.bucket.clone()), + |ctx| DeleteBucketTagging::new(ctx.client.clone(), ctx.bucket.clone()), ) } diff --git a/benches/s3/bench_bucket_versioning.rs b/benches/s3/bench_bucket_versioning.rs index 73b78f5..23d004a 100644 --- a/benches/s3/bench_bucket_versioning.rs +++ b/benches/s3/bench_bucket_versioning.rs @@ -16,7 +16,7 @@ use crate::common_benches::{Ctx2, benchmark_s3_api, skip_express_mode}; use criterion::Criterion; -use minio::s3::builders::{GetBucketVersioning, SetBucketVersioning, VersioningStatus}; +use minio::s3::builders::{GetBucketVersioning, PutBucketVersioning, VersioningStatus}; pub(crate) fn bench_get_bucket_versioning(criterion: &mut Criterion) { if skip_express_mode("bench_get_bucket_versioning") { @@ -29,16 +29,16 @@ pub(crate) fn bench_get_bucket_versioning(criterion: &mut Criterion) { |ctx| GetBucketVersioning::new(ctx.client.clone(), ctx.bucket.clone()), ) } -pub(crate) fn bench_set_bucket_versioning(criterion: &mut Criterion) { - if skip_express_mode("bench_set_bucket_versioning") { +pub(crate) fn bench_put_bucket_versioning(criterion: &mut Criterion) { + if skip_express_mode("bench_put_bucket_versioning") { return; } benchmark_s3_api( - "set_bucket_versioning", + "put_bucket_versioning", criterion, || async { Ctx2::new().await }, |ctx| { - SetBucketVersioning::new(ctx.client.clone(), ctx.bucket.clone()) + PutBucketVersioning::new(ctx.client.clone(), ctx.bucket.clone()) .versioning_status(VersioningStatus::Enabled) }, ) diff --git a/benches/s3/bench_object_legal_hold.rs b/benches/s3/bench_object_legal_hold.rs index d794013..3291166 100644 --- a/benches/s3/bench_object_legal_hold.rs +++ b/benches/s3/bench_object_legal_hold.rs @@ -16,59 +16,39 @@ use crate::common_benches::{Ctx2, benchmark_s3_api, skip_express_mode}; use criterion::Criterion; -use minio::s3::builders::{ - DisableObjectLegalHold, EnableObjectLegalHold, IsObjectLegalHoldEnabled, -}; +use minio::s3::builders::{GetObjectLegalHold, PutObjectLegalHold}; use minio::s3::types::S3Api; -pub(crate) fn bench_enable_object_legal_hold(criterion: &mut Criterion) { - if skip_express_mode("bench_enable_object_legal_hold") { +pub(crate) fn bench_put_object_legal_hold(criterion: &mut Criterion) { + if skip_express_mode("bench_put_object_legal_hold") { return; } benchmark_s3_api( - "enable_object_legal_hold", + "put_object_legal_hold", criterion, || async { Ctx2::new_with_object(true).await }, |ctx| { - EnableObjectLegalHold::new(ctx.client.clone(), ctx.bucket.clone(), ctx.object.clone()) + PutObjectLegalHold::new(ctx.client.clone(), ctx.bucket.clone(), ctx.object.clone()) + .legal_hold(Some(true)) }, ) } -pub(crate) fn bench_disable_object_legal_hold(criterion: &mut Criterion) { - if skip_express_mode("bench_disable_object_legal_hold") { +pub(crate) fn bench_get_object_legal_hold(criterion: &mut Criterion) { + if skip_express_mode("bench_get_object_legal_hold") { return; } benchmark_s3_api( - "disable_object_legal_hold", - criterion, - || async { Ctx2::new_with_object(true).await }, - |ctx| { - DisableObjectLegalHold::new(ctx.client.clone(), ctx.bucket.clone(), ctx.object.clone()) - }, - ) -} -pub(crate) fn bench_is_object_legal_hold(criterion: &mut Criterion) { - if skip_express_mode("bench_is_object_legal_hold") { - return; - } - benchmark_s3_api( - "is_object_legal_hold", + "get_object_legal_hold", criterion, || async { let ctx = Ctx2::new_with_object(true).await; ctx.client - .enable_object_legal_hold(&ctx.bucket, &ctx.object) + .get_object_legal_hold(&ctx.bucket, &ctx.object) .send() .await .unwrap(); ctx }, - |ctx| { - IsObjectLegalHoldEnabled::new( - ctx.client.clone(), - ctx.bucket.clone(), - ctx.object.clone(), - ) - }, + |ctx| GetObjectLegalHold::new(ctx.client.clone(), ctx.bucket.clone(), ctx.object.clone()), ) } diff --git a/benches/s3/bench_object_lock_config.rs b/benches/s3/bench_object_lock_config.rs index be7af83..a60b78b 100644 --- a/benches/s3/bench_object_lock_config.rs +++ b/benches/s3/bench_object_lock_config.rs @@ -15,20 +15,20 @@ use crate::common_benches::{Ctx2, benchmark_s3_api, skip_express_mode}; use criterion::Criterion; -use minio::s3::builders::{DeleteObjectLockConfig, GetObjectLockConfig, SetObjectLockConfig}; +use minio::s3::builders::{DeleteObjectLockConfig, GetObjectLockConfig, PutObjectLockConfig}; use minio_common::example::create_object_lock_config_example; -pub(crate) fn bench_set_object_lock_config(criterion: &mut Criterion) { - if skip_express_mode("bench_set_object_lock_config") { +pub(crate) fn bench_put_object_lock_config(criterion: &mut Criterion) { + if skip_express_mode("bench_put_object_lock_config") { return; } benchmark_s3_api( - "set_object_lock_config", + "put_object_lock_config", criterion, || async { Ctx2::new_with_object(true).await }, |ctx| { let config = create_object_lock_config_example(); - SetObjectLockConfig::new(ctx.client.clone(), ctx.bucket.clone()).config(config) + PutObjectLockConfig::new(ctx.client.clone(), ctx.bucket.clone()).config(config) }, ) } diff --git a/benches/s3/bench_object_retention.rs b/benches/s3/bench_object_retention.rs index 36c1407..42a73ee 100644 --- a/benches/s3/bench_object_retention.rs +++ b/benches/s3/bench_object_retention.rs @@ -16,21 +16,21 @@ use crate::common_benches::{Ctx2, benchmark_s3_api, skip_express_mode}; use criterion::Criterion; -use minio::s3::builders::{GetObjectRetention, SetObjectRetention}; -use minio::s3::response::SetObjectRetentionResponse; +use minio::s3::builders::{GetObjectRetention, PutObjectRetention}; +use minio::s3::response::PutObjectRetentionResponse; use minio::s3::types::{RetentionMode, S3Api}; use minio::s3::utils::utc_now; -pub(crate) fn bench_set_object_retention(criterion: &mut Criterion) { - if skip_express_mode("bench_set_object_retention") { +pub(crate) fn bench_put_object_retention(criterion: &mut Criterion) { + if skip_express_mode("bench_put_object_retention") { return; } benchmark_s3_api( - "set_object_retention", + "put_object_retention", criterion, || async { Ctx2::new_with_object(true).await }, |ctx| { - SetObjectRetention::new(ctx.client.clone(), ctx.bucket.clone(), ctx.object.clone()) + PutObjectRetention::new(ctx.client.clone(), ctx.bucket.clone(), ctx.object.clone()) .retention_mode(Some(RetentionMode::GOVERNANCE)) .retain_until_date(Some(utc_now() + chrono::Duration::days(1))) }, @@ -45,8 +45,8 @@ pub(crate) fn bench_get_object_retention(criterion: &mut Criterion) { criterion, || async { let ctx = Ctx2::new_with_object(true).await; - let _resp: SetObjectRetentionResponse = - SetObjectRetention::new(ctx.client.clone(), ctx.bucket.clone(), ctx.object.clone()) + let _resp: PutObjectRetentionResponse = + PutObjectRetention::new(ctx.client.clone(), ctx.bucket.clone(), ctx.object.clone()) .retention_mode(Some(RetentionMode::GOVERNANCE)) .retain_until_date(Some(utc_now() + chrono::Duration::days(1))) .send() diff --git a/benches/s3/bench_object_tags.rs b/benches/s3/bench_object_tagging.rs similarity index 64% rename from benches/s3/bench_object_tags.rs rename to benches/s3/bench_object_tagging.rs index 60436e6..cb260a5 100644 --- a/benches/s3/bench_object_tags.rs +++ b/benches/s3/bench_object_tagging.rs @@ -16,44 +16,44 @@ use crate::common_benches::{Ctx2, benchmark_s3_api, skip_express_mode}; use criterion::Criterion; -use minio::s3::builders::{GetObjectTags, SetObjectTags}; -use minio::s3::response::SetObjectTagsResponse; +use minio::s3::builders::{GetObjectTagging, PutObjectTagging}; +use minio::s3::response::PutObjectTaggingResponse; use minio::s3::types::S3Api; use minio_common::example::create_tags_example; -pub(crate) fn bench_set_object_tags(criterion: &mut Criterion) { - if skip_express_mode("bench_set_object_tags") { +pub(crate) fn bench_put_object_tagging(criterion: &mut Criterion) { + if skip_express_mode("bench_put_object_tagging") { return; } benchmark_s3_api( - "set_object_tags", + "put_object_tagging", criterion, || async { Ctx2::new_with_object(false).await }, |ctx| { - SetObjectTags::new(ctx.client.clone(), ctx.bucket.clone(), ctx.object.clone()) + PutObjectTagging::new(ctx.client.clone(), ctx.bucket.clone(), ctx.object.clone()) .tags(create_tags_example()) }, ) } -pub(crate) fn bench_get_object_tags(criterion: &mut Criterion) { - if skip_express_mode("bench_get_object_tags") { +pub(crate) fn bench_get_object_tagging(criterion: &mut Criterion) { + if skip_express_mode("bench_get_object_tagging") { return; } benchmark_s3_api( - "get_object_tags", + "get_object_tagging", criterion, || async { let ctx = Ctx2::new_with_object(false).await; - let _resp: SetObjectTagsResponse = ctx + let _resp: PutObjectTaggingResponse = ctx .client - .set_object_tags(&ctx.bucket, &ctx.object) + .put_object_tagging(&ctx.bucket, &ctx.object) .tags(create_tags_example()) .send() .await .unwrap(); ctx }, - |ctx| GetObjectTags::new(ctx.client.clone(), ctx.bucket.clone(), ctx.object.clone()), + |ctx| GetObjectTagging::new(ctx.client.clone(), ctx.bucket.clone(), ctx.object.clone()), ) } diff --git a/benches/s3/common_benches.rs b/benches/s3/common_benches.rs index d6556da..514f9cf 100644 --- a/benches/s3/common_benches.rs +++ b/benches/s3/common_benches.rs @@ -16,7 +16,7 @@ use criterion::Criterion; use minio::s3::Client; use minio::s3::error::Error; -use minio::s3::response::{MakeBucketResponse, PutObjectContentResponse}; +use minio::s3::response::{CreateBucketResponse, PutObjectContentResponse}; use minio::s3::types::{FromS3Response, S3Api, S3Request}; use minio_common::cleanup_guard::CleanupGuard; use minio_common::test_context::TestContext; @@ -61,9 +61,9 @@ impl Ctx2 { } let ctx = TestContext::new_from_env(); let bucket_name: String = rand_bucket_name(); - let _resp: MakeBucketResponse = ctx + let _resp: CreateBucketResponse = ctx .client - .make_bucket(&bucket_name) + .create_bucket(&bucket_name) .object_lock(object_lock) .send() .await @@ -92,9 +92,9 @@ impl Ctx2 { let bucket_name: String = rand_bucket_name(); self.aux_bucket = Some(bucket_name.clone()); self._aux_cleanup = Some(CleanupGuard::new(self.client.clone(), &bucket_name)); - let _resp: MakeBucketResponse = self + let _resp: CreateBucketResponse = self .client - .make_bucket(&bucket_name) + .create_bucket(&bucket_name) .object_lock(false) .send() .await diff --git a/common/src/cleanup_guard.rs b/common/src/cleanup_guard.rs index a809b11..82383b9 100644 --- a/common/src/cleanup_guard.rs +++ b/common/src/cleanup_guard.rs @@ -50,7 +50,7 @@ impl Drop for CleanupGuard { // do the actual removal of the bucket match timeout( std::time::Duration::from_secs(60), - client.remove_and_purge_bucket(&bucket_name), + client.delete_and_purge_bucket(&bucket_name), ) .await { diff --git a/common/src/test_context.rs b/common/src/test_context.rs index a357459..db25213 100644 --- a/common/src/test_context.rs +++ b/common/src/test_context.rs @@ -151,7 +151,12 @@ impl TestContext { /// ``` pub async fn create_bucket_helper(&self) -> (String, CleanupGuard) { let bucket_name = rand_bucket_name(); - let _resp = self.client.make_bucket(&bucket_name).send().await.unwrap(); + let _resp = self + .client + .create_bucket(&bucket_name) + .send() + .await + .unwrap(); let guard = CleanupGuard::new(self.client.clone(), &bucket_name); (bucket_name, guard) } diff --git a/examples/bucket_encryption.rs b/examples/bucket_encryption.rs index d91aa13..bca54e0 100644 --- a/examples/bucket_encryption.rs +++ b/examples/bucket_encryption.rs @@ -17,7 +17,7 @@ mod common; use crate::common::{create_bucket_if_not_exists, create_client_on_play}; use minio::s3::Client; -use minio::s3::response::{GetBucketEncryptionResponse, SetBucketEncryptionResponse}; +use minio::s3::response::{GetBucketEncryptionResponse, PutBucketEncryptionResponse}; use minio::s3::types::{S3Api, SseConfig}; #[tokio::main] @@ -35,8 +35,8 @@ async fn main() -> Result<(), Box> { let config = SseConfig::default(); log::info!("going to set encryption config={:?}", config); - let _resp: SetBucketEncryptionResponse = client - .set_bucket_encryption(bucket_name) + let _resp: PutBucketEncryptionResponse = client + .put_bucket_encryption(bucket_name) .sse_config(config.clone()) .send() .await?; diff --git a/examples/bucket_lifecycle.rs b/examples/bucket_lifecycle.rs index 1acfaf3..5e2ea62 100644 --- a/examples/bucket_lifecycle.rs +++ b/examples/bucket_lifecycle.rs @@ -18,7 +18,7 @@ mod common; use crate::common::{create_bucket_if_not_exists, create_client_on_play}; use minio::s3::Client; use minio::s3::response::{ - DeleteBucketLifecycleResponse, GetBucketLifecycleResponse, SetBucketLifecycleResponse, + DeleteBucketLifecycleResponse, GetBucketLifecycleResponse, PutBucketLifecycleResponse, }; use minio::s3::types::{Filter, LifecycleConfig, LifecycleRule, S3Api}; @@ -57,8 +57,8 @@ async fn main() -> Result<(), Box> { transition_storage_class: None, }]; - let resp: SetBucketLifecycleResponse = client - .set_bucket_lifecycle(bucket_name) + let resp: PutBucketLifecycleResponse = client + .put_bucket_lifecycle(bucket_name) .life_cycle_config(LifecycleConfig { rules }) .send() .await?; diff --git a/examples/bucket_versioning.rs b/examples/bucket_versioning.rs index 3a823c1..838cf75 100644 --- a/examples/bucket_versioning.rs +++ b/examples/bucket_versioning.rs @@ -18,7 +18,7 @@ mod common; use crate::common::{create_bucket_if_not_exists, create_client_on_play}; use minio::s3::Client; use minio::s3::builders::VersioningStatus; -use minio::s3::response::{GetBucketVersioningResponse, SetBucketVersioningResponse}; +use minio::s3::response::{GetBucketVersioningResponse, PutBucketVersioningResponse}; use minio::s3::types::S3Api; #[tokio::main] @@ -37,8 +37,8 @@ async fn main() -> Result<(), Box> { resp.mfa_delete ); - let _resp: SetBucketVersioningResponse = client - .set_bucket_versioning(bucket_name) + let _resp: PutBucketVersioningResponse = client + .put_bucket_versioning(bucket_name) .versioning_status(VersioningStatus::Enabled) .send() .await?; @@ -52,8 +52,8 @@ async fn main() -> Result<(), Box> { resp.mfa_delete ); - let _resp: SetBucketVersioningResponse = client - .set_bucket_versioning(bucket_name) + let _resp: PutBucketVersioningResponse = client + .put_bucket_versioning(bucket_name) .versioning_status(VersioningStatus::Suspended) .send() .await?; @@ -67,8 +67,8 @@ async fn main() -> Result<(), Box> { resp.mfa_delete ); - let _resp: SetBucketVersioningResponse = client - .set_bucket_versioning(bucket_name) + let _resp: PutBucketVersioningResponse = client + .put_bucket_versioning(bucket_name) //.versioning_status(VersioningStatus::Suspended) .send() .await?; diff --git a/examples/common.rs b/examples/common.rs index 69a170f..1d3ad44 100644 --- a/examples/common.rs +++ b/examples/common.rs @@ -43,7 +43,7 @@ pub async fn create_bucket_if_not_exists( // Make 'bucket_name' bucket if not exist. if !resp.exists { - client.make_bucket(bucket_name).send().await.unwrap(); + client.create_bucket(bucket_name).send().await.unwrap(); }; Ok(()) } diff --git a/examples/object_prompt.rs b/examples/object_prompt.rs index 8dfa8d7..76cdda9 100644 --- a/examples/object_prompt.rs +++ b/examples/object_prompt.rs @@ -20,7 +20,7 @@ use minio::s3::builders::ObjectContent; use minio::s3::client::ClientBuilder; use minio::s3::creds::StaticProvider; use minio::s3::http::BaseUrl; -use minio::s3::response::ObjectPromptResponse; +use minio::s3::response::GetObjectPromptResponse; use minio::s3::types::S3Api; use std::path::Path; @@ -66,8 +66,8 @@ async fn main() -> Result<(), Box> { filename.display() ); - let resp: ObjectPromptResponse = client - .object_prompt(bucket_name, object_name, "what is it about?") + let resp: GetObjectPromptResponse = client + .get_object_prompt(bucket_name, object_name, "what is it about?") //.lambda_arn("arn:minio:s3-object-lambda::_:webhook") // this is the default value .send() .await?; diff --git a/examples/put_object.rs b/examples/put_object.rs index 374552d..32aa74e 100644 --- a/examples/put_object.rs +++ b/examples/put_object.rs @@ -48,7 +48,7 @@ async fn main() -> Result<(), Box> { let resp: BucketExistsResponse = client.bucket_exists(&args.bucket).send().await.unwrap(); if !resp.exists { - client.make_bucket(&args.bucket).send().await.unwrap(); + client.create_bucket(&args.bucket).send().await.unwrap(); } let content = ObjectContent::from(args.file.as_path()); diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..c579cf1 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,4 @@ +[toolchain] +channel = "1.86.0" +components = ["clippy", "rustfmt"] +#targets = ["x86_64-unknown-linux-musl"] \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 41ca111..39e92c7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,7 +13,48 @@ // See the License for the specific language governing permissions and // limitations under the License. -#![allow(clippy::tabs_in_doc_comments)] +//! # MinIO Rust SDK (`minio-rs`) +//! +//! This crate provides a strongly-typed, async-first interface to the MinIO and Amazon S3-compatible object storage APIs. +//! +//! Each supported S3 operation has a corresponding request builder (e.g., [`BucketExists`], [`PutObject`], [`UploadPartCopy`]), +//! which allows users to configure request parameters using a fluent builder pattern. +//! +//! All request builders implement the [`S3Api`] trait, which provides the async [`send`](crate::s3::types::S3Api::send) method +//! to execute the request and return a typed response. +//! +//! ## Basic Usage +//! +//! ```no_run +//! use minio::s3::Client; +//! use minio::s3::types::S3Api; +//! use minio::s3::response::BucketExistsResponse; +//! +//! #[tokio::main] +//! async fn main() { +//! let client: Client = Default::default(); // configure your client +//! +//! let exists: BucketExistsResponse = client +//! .bucket_exists("my-bucket") +//! .send() +//! .await +//! .expect("request failed"); +//! +//! println!("Bucket exists: {}", exists.exists); +//! } +//! ``` +//! +//! ## Features +//! - Request builder pattern for ergonomic API usage +//! - Full async/await support via [`tokio`] +//! - Strongly-typed responses +//! - Transparent error handling via `Result` +//! +//! ## Design +//! - Each API method on the [`Client`] returns a builder struct +//! - Builders implement [`ToS3Request`] for request conversion and [`S3Api`] for execution +//! - Responses implement [`FromS3Response`] for consistent deserialization + #![allow(clippy::result_large_err)] #![allow(clippy::too_many_arguments)] pub mod s3; diff --git a/src/s3/builders.rs b/src/s3/builders.rs index 59de2da..b57562d 100644 --- a/src/s3/builders.rs +++ b/src/s3/builders.rs @@ -19,50 +19,49 @@ mod append_object; mod bucket_common; mod bucket_exists; mod copy_object; +mod create_bucket; +mod delete_bucket; mod delete_bucket_encryption; mod delete_bucket_lifecycle; mod delete_bucket_notification; mod delete_bucket_policy; mod delete_bucket_replication; -mod delete_bucket_tags; +mod delete_bucket_tagging; mod delete_object_lock_config; -mod delete_object_tags; -mod disable_object_legal_hold; -mod enable_object_legal_hold; +mod delete_object_tagging; +mod delete_objects; mod get_bucket_encryption; mod get_bucket_lifecycle; mod get_bucket_notification; mod get_bucket_policy; mod get_bucket_replication; -mod get_bucket_tags; +mod get_bucket_tagging; mod get_bucket_versioning; mod get_object; +mod get_object_legal_hold; mod get_object_lock_config; +mod get_object_prompt; mod get_object_retention; -mod get_object_tags; +mod get_object_tagging; mod get_presigned_object_url; mod get_presigned_policy_form_data; mod get_region; -mod is_object_legal_hold_enabled; +mod list_bucket_notification; mod list_buckets; mod list_objects; -mod listen_bucket_notification; -mod make_bucket; -mod object_prompt; +mod put_bucket_encryption; +mod put_bucket_lifecycle; +mod put_bucket_notification; +mod put_bucket_policy; +mod put_bucket_replication; +mod put_bucket_tagging; +mod put_bucket_versioning; mod put_object; -mod remove_bucket; -mod remove_objects; +mod put_object_legal_hold; +mod put_object_lock_config; +mod put_object_retention; +mod put_object_tagging; mod select_object_content; -mod set_bucket_encryption; -mod set_bucket_lifecycle; -mod set_bucket_notification; -mod set_bucket_policy; -mod set_bucket_replication; -mod set_bucket_tags; -mod set_bucket_versioning; -mod set_object_lock_config; -mod set_object_retention; -mod set_object_tags; mod stat_object; pub use crate::s3::object_content::*; @@ -70,48 +69,47 @@ pub use append_object::*; pub use bucket_common::*; pub use bucket_exists::*; pub use copy_object::*; +pub use create_bucket::*; +pub use delete_bucket::*; pub use delete_bucket_encryption::*; pub use delete_bucket_lifecycle::*; pub use delete_bucket_notification::*; pub use delete_bucket_policy::*; pub use delete_bucket_replication::*; -pub use delete_bucket_tags::*; +pub use delete_bucket_tagging::*; pub use delete_object_lock_config::*; -pub use delete_object_tags::*; -pub use disable_object_legal_hold::*; -pub use enable_object_legal_hold::*; +pub use delete_object_tagging::*; +pub use delete_objects::*; pub use get_bucket_encryption::*; pub use get_bucket_lifecycle::*; pub use get_bucket_notification::*; pub use get_bucket_policy::*; pub use get_bucket_replication::*; -pub use get_bucket_tags::*; +pub use get_bucket_tagging::*; pub use get_bucket_versioning::*; pub use get_object::*; +pub use get_object_legal_hold::*; pub use get_object_lock_config::*; +pub use get_object_prompt::*; pub use get_object_retention::*; -pub use get_object_tags::*; +pub use get_object_tagging::*; pub use get_presigned_object_url::*; pub use get_presigned_policy_form_data::*; pub use get_region::*; -pub use is_object_legal_hold_enabled::*; +pub use list_bucket_notification::*; pub use list_buckets::*; pub use list_objects::*; -pub use listen_bucket_notification::*; -pub use make_bucket::*; -pub use object_prompt::*; +pub use put_bucket_encryption::*; +pub use put_bucket_lifecycle::*; +pub use put_bucket_notification::*; +pub use put_bucket_policy::*; +pub use put_bucket_replication::*; +pub use put_bucket_tagging::*; +pub use put_bucket_versioning::*; pub use put_object::*; -pub use remove_bucket::*; -pub use remove_objects::*; +pub use put_object_legal_hold::*; +pub use put_object_lock_config::*; +pub use put_object_retention::*; +pub use put_object_tagging::*; pub use select_object_content::*; -pub use set_bucket_encryption::*; -pub use set_bucket_lifecycle::*; -pub use set_bucket_notification::*; -pub use set_bucket_policy::*; -pub use set_bucket_replication::*; -pub use set_bucket_tags::*; -pub use set_bucket_versioning::*; -pub use set_object_lock_config::*; -pub use set_object_retention::*; -pub use set_object_tags::*; pub use stat_object::*; diff --git a/src/s3/builders/append_object.rs b/src/s3/builders/append_object.rs index 71b3c04..2096794 100644 --- a/src/s3/builders/append_object.rs +++ b/src/s3/builders/append_object.rs @@ -28,7 +28,11 @@ use http::Method; use std::sync::Arc; // region: append-object -#[derive(Debug, Clone, Default)] + +/// 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. +#[derive(Clone, Debug, Default)] pub struct AppendObject { client: Client, @@ -107,9 +111,14 @@ impl ToS3Request for AppendObject { // region: append-object-content -/// AppendObjectContent takes a `ObjectContent` stream and appends it to MinIO/S3. +/// Argument builder for the [`AppendObject`](https://docs.aws.amazon.com/AmazonS3/latest/userguide/directory-buckets-objects-append.html) S3 API operation. /// -/// It is a higher level API and handles multipart appends transparently. +/// This struct constructs the parameters required for the [`Client::append_object_content`](crate::s3::client::Client::append_object_content) method. +/// 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, +/// managing multipart upload details internally. +#[derive(Default)] pub struct AppendObjectContent { client: Client, @@ -284,12 +293,7 @@ impl AppendObjectContent { part_number += 1; let buffer_size = part_content.len() as u64; - assert!( - buffer_size <= part_size, - "{:?} <= {:?}", - buffer_size, - part_size - ); + assert!(buffer_size <= part_size, "{buffer_size} <= {part_size}",); if buffer_size == 0 && part_number > 1 { // We are done as we appended at least 1 part and we have diff --git a/src/s3/builders/bucket_common.rs b/src/s3/builders/bucket_common.rs index 6ee9b34..50f9c41 100644 --- a/src/s3/builders/bucket_common.rs +++ b/src/s3/builders/bucket_common.rs @@ -18,7 +18,7 @@ use std::marker::PhantomData; use crate::s3::client::Client; use crate::s3::multimap::Multimap; -#[derive(Clone, Default)] +#[derive(Clone, Debug, Default)] pub struct BucketCommon { pub(crate) client: Client, diff --git a/src/s3/builders/bucket_exists.rs b/src/s3/builders/bucket_exists.rs index ee9f8e1..27e070d 100644 --- a/src/s3/builders/bucket_exists.rs +++ b/src/s3/builders/bucket_exists.rs @@ -20,10 +20,10 @@ use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::utils::check_bucket_name; use http::Method; -/// Argument builder for [bucket_exists()](Client::bucket_exists) API +/// This struct constructs the parameters required for the [`Client::bucket_exists`](crate::s3::client::Client::bucket_exists) method. pub type BucketExists = BucketCommon; -#[derive(Default, Debug)] +#[derive(Clone, Debug, Default)] pub struct BucketExistsPhantomData; impl S3Api for BucketExists { diff --git a/src/s3/builders/copy_object.rs b/src/s3/builders/copy_object.rs index a4d4fe5..4896e37 100644 --- a/src/s3/builders/copy_object.rs +++ b/src/s3/builders/copy_object.rs @@ -31,7 +31,9 @@ use http::Method; use std::collections::HashMap; use std::sync::Arc; -/// Argument builder for [UploadPartCopy](https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html) API +/// 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. #[derive(Clone, Debug, Default)] pub struct UploadPartCopy { client: Client, @@ -98,8 +100,7 @@ impl ToS3Request for UploadPartCopy { } if !(1..=MAX_MULTIPART_COUNT).contains(&self.part_number) { return Err(Error::InvalidPartNumber(format!( - "part number must be between 1 and {}", - MAX_MULTIPART_COUNT + "part number must be between 1 and {MAX_MULTIPART_COUNT}" ))); } } @@ -325,7 +326,7 @@ impl ToS3Request for CopyObjectInternal { } } -/// Argument builder for [copy_object()](Client::copy_object_old) API +/// Argument builder for [copy_object()](Client::copy_object) API #[derive(Clone, Debug, Default)] pub struct CopyObject { client: Client, @@ -409,9 +410,7 @@ impl CopyObject { self.tagging_directive = tagging_directive; self } -} -impl CopyObject { pub async fn send(self) -> Result { { if let Some(v) = &self.sse { @@ -612,9 +611,7 @@ impl ComposeObjectInternal { self.sources = sources; self } -} -impl ComposeObjectInternal { #[async_recursion] pub async fn send(self) -> (Result, String) { let mut upload_id = String::new(); @@ -754,7 +751,7 @@ impl ComposeObjectInternal { let mut headers_copy = headers.clone(); headers_copy.add( "x-amz-copy-source-range", - format!("bytes={}-{}", offset, end_bytes), + format!("bytes={offset}-{end_bytes}"), ); let resp: UploadPartCopyResponse = match self @@ -885,9 +882,7 @@ impl ComposeObject { self.sources = sources; self } -} -impl ComposeObject { pub async fn send(self) -> Result { { if let Some(v) = &self.sse { @@ -934,7 +929,7 @@ impl ComposeObject { // region: misc #[derive(Clone, Debug, Default)] -/// Source object information for [compose object argument](ComposeObjectArgs) +/// Source object information for [compose_object](Client::compose_object) pub struct ComposeSource { pub extra_headers: Option, pub extra_query_params: Option, @@ -963,35 +958,23 @@ impl ComposeSource { /// use minio::s3::builders::ComposeSource; /// let src = ComposeSource::new("my-src-bucket", "my-src-object").unwrap(); /// ``` - pub fn new(bucket_name: &str, object_name: &str) -> Result { + pub fn new(bucket_name: &str, object_name: &str) -> Result { check_bucket_name(bucket_name, true)?; check_object_name(object_name)?; - Ok(ComposeSource { - extra_headers: None, - extra_query_params: None, - region: None, + Ok(Self { bucket: bucket_name.to_owned(), object: object_name.to_owned(), - version_id: None, - ssec: None, - offset: None, - length: None, - match_etag: None, - not_match_etag: None, - modified_since: None, - unmodified_since: None, - object_size: None, - headers: None, + ..Default::default() }) } pub fn get_object_size(&self) -> u64 { - self.object_size.expect("A: ABORT: ComposeSource::build_headers() must be called prior to this method invocation. This shoud not happen.") + self.object_size.expect("A: ABORT: ComposeSource::build_headers() must be called prior to this method invocation. This should not happen.") } pub fn get_headers(&self) -> Multimap { - self.headers.as_ref().expect("B: ABORT: ComposeSource::build_headers() must be called prior to this method invocation. This shoud not happen.").clone() + self.headers.as_ref().expect("B: ABORT: ComposeSource::build_headers() must be called prior to this method invocation. This should not happen.").clone() } pub fn build_headers(&mut self, object_size: u64, etag: String) -> Result<(), Error> { @@ -1098,24 +1081,14 @@ pub struct CopySource { } impl CopySource { - pub fn new(bucket_name: &str, object_name: &str) -> Result { + pub fn new(bucket_name: &str, object_name: &str) -> Result { check_bucket_name(bucket_name, true)?; check_object_name(object_name)?; - Ok(CopySource { - extra_headers: None, - extra_query_params: None, - region: None, + Ok(Self { bucket: bucket_name.to_owned(), object: object_name.to_owned(), - version_id: None, - ssec: None, - offset: None, - length: None, - match_etag: None, - not_match_etag: None, - modified_since: None, - unmodified_since: None, + ..Default::default() }) } @@ -1178,20 +1151,20 @@ fn into_headers_copy_object( } if !tagging.is_empty() { - map.insert("x-amz-tagging".into(), tagging); + map.add("x-amz-tagging", tagging); } } if let Some(v) = retention { - map.insert("x-amz-object-lock-mode".into(), v.mode.to_string()); - map.insert( - "x-amz-object-lock-retain-until-date".into(), + map.add("x-amz-object-lock-mode", v.mode.to_string()); + map.add( + "x-amz-object-lock-retain-until-date", to_iso8601utc(v.retain_until_date), ); } if legal_hold { - map.insert("x-amz-object-lock-legal-hold".into(), "ON".into()); + map.add("x-amz-object-lock-legal-hold", "ON"); } map diff --git a/src/s3/builders/make_bucket.rs b/src/s3/builders/create_bucket.rs similarity index 86% rename from src/s3/builders/make_bucket.rs rename to src/s3/builders/create_bucket.rs index 20b632d..a6b0125 100644 --- a/src/s3/builders/make_bucket.rs +++ b/src/s3/builders/create_bucket.rs @@ -17,15 +17,17 @@ use crate::s3::Client; use crate::s3::client::DEFAULT_REGION; use crate::s3::error::Error; use crate::s3::multimap::{Multimap, MultimapExt}; -use crate::s3::response::MakeBucketResponse; +use crate::s3::response::CreateBucketResponse; use crate::s3::segmented_bytes::SegmentedBytes; use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::utils::check_bucket_name; use http::Method; -/// Argument builder for [make_bucket()](Client::make_bucket) API +/// 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. #[derive(Clone, Debug, Default)] -pub struct MakeBucket { +pub struct CreateBucket { client: Client, extra_headers: Option, @@ -36,7 +38,7 @@ pub struct MakeBucket { object_lock: bool, } -impl MakeBucket { +impl CreateBucket { pub fn new(client: Client, bucket: String) -> Self { Self { client, @@ -66,11 +68,11 @@ impl MakeBucket { } } -impl S3Api for MakeBucket { - type S3Response = MakeBucketResponse; +impl S3Api for CreateBucket { + type S3Response = CreateBucketResponse; } -impl ToS3Request for MakeBucket { +impl ToS3Request for CreateBucket { fn to_s3request(self) -> Result { check_bucket_name(&self.bucket, true)?; @@ -95,8 +97,7 @@ impl ToS3Request for MakeBucket { let data: String = match region_str.as_str() { DEFAULT_REGION => String::new(), _ => format!( - "{}", - region_str + "{region_str}", ), }; diff --git a/src/s3/builders/remove_bucket.rs b/src/s3/builders/delete_bucket.rs similarity index 67% rename from src/s3/builders/remove_bucket.rs rename to src/s3/builders/delete_bucket.rs index 5357789..21e9986 100644 --- a/src/s3/builders/remove_bucket.rs +++ b/src/s3/builders/delete_bucket.rs @@ -15,22 +15,24 @@ use crate::s3::builders::BucketCommon; use crate::s3::error::Error; -use crate::s3::response::RemoveBucketResponse; +use crate::s3::response::DeleteBucketResponse; use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::utils::check_bucket_name; use http::Method; -/// Argument builder for [remove_bucket()](Client::remove_bucket) API -pub type RemoveBucket = BucketCommon; +/// Argument builder for the [`GetBucketEncryption`](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. +pub type DeleteBucket = BucketCommon; -#[derive(Default, Debug)] -pub struct RemoveBucketPhantomData; +#[derive(Clone, Debug, Default)] +pub struct DeleteBucketPhantomData; -impl S3Api for RemoveBucket { - type S3Response = RemoveBucketResponse; +impl S3Api for DeleteBucket { + type S3Response = DeleteBucketResponse; } -impl ToS3Request for RemoveBucket { +impl ToS3Request for DeleteBucket { fn to_s3request(self) -> Result { check_bucket_name(&self.bucket, true)?; diff --git a/src/s3/builders/delete_bucket_encryption.rs b/src/s3/builders/delete_bucket_encryption.rs index dca4292..5dc921b 100644 --- a/src/s3/builders/delete_bucket_encryption.rs +++ b/src/s3/builders/delete_bucket_encryption.rs @@ -20,10 +20,12 @@ use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::utils::{check_bucket_name, insert}; use http::Method; -/// Argument builder for [delete_bucket_encryption()](Client::delete_bucket_encryption) API +/// 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. pub type DeleteBucketEncryption = BucketCommon; -#[derive(Default, Debug)] +#[derive(Clone, Debug, Default)] pub struct DeleteBucketEncryptionPhantomData; impl S3Api for DeleteBucketEncryption { diff --git a/src/s3/builders/delete_bucket_lifecycle.rs b/src/s3/builders/delete_bucket_lifecycle.rs index 5ae4b23..c8eb148 100644 --- a/src/s3/builders/delete_bucket_lifecycle.rs +++ b/src/s3/builders/delete_bucket_lifecycle.rs @@ -20,10 +20,12 @@ use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::utils::{check_bucket_name, insert}; use http::Method; -/// Argument builder for [delete_bucket_lifecycle()](Client::delete_bucket_lifecycle) API +/// 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. pub type DeleteBucketLifecycle = BucketCommon; -#[derive(Default, Debug)] +#[derive(Clone, Debug, Default)] pub struct DeleteBucketLifecyclePhantomData; impl S3Api for DeleteBucketLifecycle { diff --git a/src/s3/builders/delete_bucket_notification.rs b/src/s3/builders/delete_bucket_notification.rs index ac50b7a..ddfcef4 100644 --- a/src/s3/builders/delete_bucket_notification.rs +++ b/src/s3/builders/delete_bucket_notification.rs @@ -22,10 +22,10 @@ use crate::s3::utils::{check_bucket_name, insert}; use bytes::Bytes; use http::Method; -/// Argument builder for [delete_bucket_notification()](Client::delete_bucket_notification) API +/// This struct constructs the parameters required for the [`Client::delete_bucket_notification`](crate::s3::client::Client::delete_bucket_notification) method. pub type DeleteBucketNotification = BucketCommon; -#[derive(Default, Debug)] +#[derive(Clone, Debug, Default)] pub struct DeleteBucketNotificationPhantomData; impl S3Api for DeleteBucketNotification { diff --git a/src/s3/builders/delete_bucket_policy.rs b/src/s3/builders/delete_bucket_policy.rs index bcb1483..3a400fb 100644 --- a/src/s3/builders/delete_bucket_policy.rs +++ b/src/s3/builders/delete_bucket_policy.rs @@ -20,10 +20,12 @@ use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::utils::{check_bucket_name, insert}; use http::Method; -/// Argument builder for [delete_bucket_policy()](Client::delete_bucket_policy) API +/// 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. pub type DeleteBucketPolicy = BucketCommon; -#[derive(Default, Debug)] +#[derive(Clone, Debug, Default)] pub struct DeleteBucketPolicyPhantomData; impl S3Api for DeleteBucketPolicy { diff --git a/src/s3/builders/delete_bucket_replication.rs b/src/s3/builders/delete_bucket_replication.rs index 2f89cc1..ae9a5e6 100644 --- a/src/s3/builders/delete_bucket_replication.rs +++ b/src/s3/builders/delete_bucket_replication.rs @@ -20,10 +20,12 @@ use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::utils::{check_bucket_name, insert}; use http::Method; -/// Argument builder for [delete_bucket_replication()](Client::delete_bucket_replication) API +/// 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. pub type DeleteBucketReplication = BucketCommon; -#[derive(Default, Debug)] +#[derive(Clone, Debug, Default)] pub struct DeleteBucketReplicationPhantomData; impl S3Api for DeleteBucketReplication { diff --git a/src/s3/builders/delete_bucket_tags.rs b/src/s3/builders/delete_bucket_tagging.rs similarity index 65% rename from src/s3/builders/delete_bucket_tags.rs rename to src/s3/builders/delete_bucket_tagging.rs index 1c10ba8..cc375bb 100644 --- a/src/s3/builders/delete_bucket_tags.rs +++ b/src/s3/builders/delete_bucket_tagging.rs @@ -15,22 +15,24 @@ use crate::s3::builders::BucketCommon; use crate::s3::error::Error; -use crate::s3::response::DeleteBucketTagsResponse; +use crate::s3::response::DeleteBucketTaggingResponse; use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::utils::{check_bucket_name, insert}; use http::Method; -/// Argument builder for [delete_bucket_tags()](Client::delete_bucket_tags) API -pub type DeleteBucketTags = BucketCommon; +/// 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. +pub type DeleteBucketTagging = BucketCommon; -#[derive(Default, Debug)] -pub struct DeleteBucketTagsPhantomData; +#[derive(Clone, Debug, Default)] +pub struct DeleteBucketTaggingPhantomData; -impl S3Api for DeleteBucketTags { - type S3Response = DeleteBucketTagsResponse; +impl S3Api for DeleteBucketTagging { + type S3Response = DeleteBucketTaggingResponse; } -impl ToS3Request for DeleteBucketTags { +impl ToS3Request for DeleteBucketTagging { fn to_s3request(self) -> Result { check_bucket_name(&self.bucket, true)?; diff --git a/src/s3/builders/delete_object_lock_config.rs b/src/s3/builders/delete_object_lock_config.rs index 39a4c4f..ad47022 100644 --- a/src/s3/builders/delete_object_lock_config.rs +++ b/src/s3/builders/delete_object_lock_config.rs @@ -22,10 +22,10 @@ use crate::s3::utils::{check_bucket_name, insert}; use bytes::Bytes; use http::Method; -/// Argument builder for [delete_object_lock_config()](Client::delete_object_lock_config) API +/// This struct constructs the parameters required for the [`Client::delete_object_lock_config`](crate::s3::client::Client::delete_object_lock_config) method. pub type DeleteObjectLockConfig = BucketCommon; -#[derive(Default, Debug)] +#[derive(Clone, Debug, Default)] pub struct DeleteObjectLockConfigPhantomData; impl S3Api for DeleteObjectLockConfig { diff --git a/src/s3/builders/delete_object_tags.rs b/src/s3/builders/delete_object_tagging.rs similarity index 81% rename from src/s3/builders/delete_object_tags.rs rename to src/s3/builders/delete_object_tagging.rs index abdb921..e6f39ef 100644 --- a/src/s3/builders/delete_object_tags.rs +++ b/src/s3/builders/delete_object_tagging.rs @@ -16,14 +16,16 @@ use crate::s3::Client; use crate::s3::error::Error; use crate::s3::multimap::{Multimap, MultimapExt}; -use crate::s3::response::DeleteObjectTagsResponse; +use crate::s3::response::DeleteObjectTaggingResponse; use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::utils::{check_bucket_name, check_object_name, insert}; use http::Method; -/// Argument builder for [delete_object_tags()](Client::delete_object_tags) API +/// 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. #[derive(Clone, Debug, Default)] -pub struct DeleteObjectTags { +pub struct DeleteObjectTagging { client: Client, extra_headers: Option, @@ -35,7 +37,7 @@ pub struct DeleteObjectTags { version_id: Option, } -impl DeleteObjectTags { +impl DeleteObjectTagging { pub fn new(client: Client, bucket: String, object: String) -> Self { Self { client, @@ -66,11 +68,11 @@ impl DeleteObjectTags { } } -impl S3Api for DeleteObjectTags { - type S3Response = DeleteObjectTagsResponse; +impl S3Api for DeleteObjectTagging { + type S3Response = DeleteObjectTaggingResponse; } -impl ToS3Request for DeleteObjectTags { +impl ToS3Request for DeleteObjectTagging { fn to_s3request(self) -> Result { check_bucket_name(&self.bucket, true)?; check_object_name(&self.object)?; diff --git a/src/s3/builders/remove_objects.rs b/src/s3/builders/delete_objects.rs similarity index 96% rename from src/s3/builders/remove_objects.rs rename to src/s3/builders/delete_objects.rs index 72ed3d4..027084f 100644 --- a/src/s3/builders/remove_objects.rs +++ b/src/s3/builders/delete_objects.rs @@ -1,5 +1,5 @@ // MinIO Rust Library for Amazon S3 Compatible Cloud Storage -// Copyright 2022-2024 MinIO, Inc. +// 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. @@ -273,7 +273,11 @@ impl ToS3Request for RemoveObjectsApi { // endregion: remove-object-api -// region: delete-object +// region: delete-objects + +/// 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`](crate::s3::client::Client::get_bucket_encryption) method. pub struct DeleteObjects { items: Pin + Send + Sync>>, } @@ -299,7 +303,7 @@ where } } -// endregion: delete-object +// endregion: delete-objects // region: remove-objects diff --git a/src/s3/builders/disable_object_legal_hold.rs b/src/s3/builders/disable_object_legal_hold.rs deleted file mode 100644 index 7094123..0000000 --- a/src/s3/builders/disable_object_legal_hold.rs +++ /dev/null @@ -1,92 +0,0 @@ -// 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 crate::s3::Client; -use crate::s3::error::Error; -use crate::s3::multimap::{Multimap, MultimapExt}; -use crate::s3::response::DisableObjectLegalHoldResponse; -use crate::s3::segmented_bytes::SegmentedBytes; -use crate::s3::types::{S3Api, S3Request, ToS3Request}; -use crate::s3::utils::{check_bucket_name, check_object_name, insert, md5sum_hash}; -use bytes::Bytes; -use http::Method; - -/// Argument builder for [disable_object_legal_hold()](Client::disable_object_legal_hold) API -#[derive(Clone, Debug, Default)] -pub struct DisableObjectLegalHold { - client: Client, - - extra_headers: Option, - extra_query_params: Option, - region: Option, - bucket: String, - - object: String, - version_id: Option, -} - -impl DisableObjectLegalHold { - 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) -> Self { - self.extra_headers = extra_headers; - self - } - - pub fn extra_query_params(mut self, extra_query_params: Option) -> Self { - self.extra_query_params = extra_query_params; - self - } - - pub fn version_id(mut self, version_id: Option) -> Self { - self.version_id = version_id; - self - } -} - -impl S3Api for DisableObjectLegalHold { - type S3Response = DisableObjectLegalHoldResponse; -} - -impl ToS3Request for DisableObjectLegalHold { - fn to_s3request(self) -> Result { - check_bucket_name(&self.bucket, true)?; - check_object_name(&self.object)?; - - let mut headers: Multimap = self.extra_headers.unwrap_or_default(); - let mut query_params: Multimap = insert(self.extra_query_params, "legal-hold"); - query_params.add_version(self.version_id); - - const PAYLOAD: &str = "OFF"; - headers.add("Content-MD5", md5sum_hash(PAYLOAD.as_ref())); - let body: Option = Some(SegmentedBytes::from(Bytes::from(PAYLOAD))); - //TODO consider const body - - Ok(S3Request::new(self.client, Method::PUT) - .region(self.region) - .bucket(Some(self.bucket)) - .query_params(query_params) - .headers(headers) - .object(Some(self.object)) - .body(body)) - } -} diff --git a/src/s3/builders/get_bucket_encryption.rs b/src/s3/builders/get_bucket_encryption.rs index dc6503a..199bffa 100644 --- a/src/s3/builders/get_bucket_encryption.rs +++ b/src/s3/builders/get_bucket_encryption.rs @@ -20,10 +20,12 @@ use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::utils::{check_bucket_name, insert}; use http::Method; -/// Argument builder for [get_bucket_encryption()](crate::s3::client::Client::get_bucket_encryption) API +/// 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. pub type GetBucketEncryption = BucketCommon; -#[derive(Default, Debug)] +#[derive(Clone, Debug, Default)] pub struct GetBucketEncryptionPhantomData; impl S3Api for GetBucketEncryption { diff --git a/src/s3/builders/get_bucket_lifecycle.rs b/src/s3/builders/get_bucket_lifecycle.rs index 99aedae..ab2554c 100644 --- a/src/s3/builders/get_bucket_lifecycle.rs +++ b/src/s3/builders/get_bucket_lifecycle.rs @@ -20,10 +20,12 @@ use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::utils::{check_bucket_name, insert}; use http::Method; -/// Argument builder for [get_bucket_lifecycle()](Client::get_bucket_lifecycle) API +/// 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. pub type GetBucketLifecycle = BucketCommon; -#[derive(Default, Debug)] +#[derive(Clone, Debug, Default)] pub struct GetBucketLifecyclePhantomData; impl S3Api for GetBucketLifecycle { diff --git a/src/s3/builders/get_bucket_notification.rs b/src/s3/builders/get_bucket_notification.rs index cdcd949..4ba959d 100644 --- a/src/s3/builders/get_bucket_notification.rs +++ b/src/s3/builders/get_bucket_notification.rs @@ -20,7 +20,9 @@ use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::utils::{check_bucket_name, insert}; use http::Method; -/// Argument builder for [get_bucket_notification()](Client::get_bucket_notification) API +/// 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. pub type GetBucketNotification = BucketCommon; #[derive(Default, Debug)] diff --git a/src/s3/builders/get_bucket_policy.rs b/src/s3/builders/get_bucket_policy.rs index 66cd0b6..0185fb9 100644 --- a/src/s3/builders/get_bucket_policy.rs +++ b/src/s3/builders/get_bucket_policy.rs @@ -20,10 +20,12 @@ use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::utils::{check_bucket_name, insert}; use http::Method; -/// Argument builder for [get_bucket_policy()](Client::get_bucket_policy) API +/// 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. pub type GetBucketPolicy = BucketCommon; -#[derive(Default, Debug)] +#[derive(Clone, Debug, Default)] pub struct GetBucketPolicyPhantomData; impl S3Api for GetBucketPolicy { diff --git a/src/s3/builders/get_bucket_replication.rs b/src/s3/builders/get_bucket_replication.rs index f7d21e4..551b594 100644 --- a/src/s3/builders/get_bucket_replication.rs +++ b/src/s3/builders/get_bucket_replication.rs @@ -20,10 +20,12 @@ use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::utils::{check_bucket_name, insert}; use http::Method; -/// Argument builder for [get_bucket_replication()](Client::get_bucket_replication) API +/// 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. pub type GetBucketReplication = BucketCommon; -#[derive(Default, Debug)] +#[derive(Clone, Debug, Default)] pub struct GetBucketReplicationPhantomData; impl S3Api for GetBucketReplication { diff --git a/src/s3/builders/get_bucket_tags.rs b/src/s3/builders/get_bucket_tagging.rs similarity index 80% rename from src/s3/builders/get_bucket_tags.rs rename to src/s3/builders/get_bucket_tagging.rs index 787da83..3fb513a 100644 --- a/src/s3/builders/get_bucket_tags.rs +++ b/src/s3/builders/get_bucket_tagging.rs @@ -16,15 +16,17 @@ use crate::s3::Client; use crate::s3::error::Error; use crate::s3::multimap::Multimap; -use crate::s3::response::GetBucketTagsResponse; +use crate::s3::response::GetBucketTaggingResponse; use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::utils::{check_bucket_name, insert}; use http::Method; use std::collections::HashMap; -/// Argument builder for [get_bucket_tags()](crate::s3::client::Client::get_bucket_tags) API +/// 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. #[derive(Clone, Debug, Default)] -pub struct GetBucketTags { +pub struct GetBucketTagging { client: Client, extra_headers: Option, @@ -35,7 +37,7 @@ pub struct GetBucketTags { tags: HashMap, } -impl GetBucketTags { +impl GetBucketTagging { pub fn new(client: Client, bucket: String) -> Self { Self { client, @@ -65,11 +67,11 @@ impl GetBucketTags { } } -impl S3Api for GetBucketTags { - type S3Response = GetBucketTagsResponse; +impl S3Api for GetBucketTagging { + type S3Response = GetBucketTaggingResponse; } -impl ToS3Request for GetBucketTags { +impl ToS3Request for GetBucketTagging { fn to_s3request(self) -> Result { check_bucket_name(&self.bucket, true)?; diff --git a/src/s3/builders/get_bucket_versioning.rs b/src/s3/builders/get_bucket_versioning.rs index 64b3cec..1e771b1 100644 --- a/src/s3/builders/get_bucket_versioning.rs +++ b/src/s3/builders/get_bucket_versioning.rs @@ -20,10 +20,12 @@ use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::utils::{check_bucket_name, insert}; use http::Method; -/// Argument builder for [get_bucket_versioning()](crate::s3::client::Client::get_bucket_versioning) API +/// 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. pub type GetBucketVersioning = BucketCommon; -#[derive(Default, Debug)] +#[derive(Clone, Debug, Default)] pub struct GetBucketVersioningPhantomData; impl S3Api for GetBucketVersioning { diff --git a/src/s3/builders/get_object.rs b/src/s3/builders/get_object.rs index 2e83eea..32a6375 100644 --- a/src/s3/builders/get_object.rs +++ b/src/s3/builders/get_object.rs @@ -26,7 +26,9 @@ use crate::s3::{ utils::{UtcTime, check_bucket_name, to_http_header_value}, }; -/// Argument builder for [list_objects()](Client::get_object) API. +/// 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. #[derive(Debug, Clone, Default)] pub struct GetObject { client: Client, diff --git a/src/s3/builders/is_object_legal_hold_enabled.rs b/src/s3/builders/get_object_legal_hold.rs similarity index 81% rename from src/s3/builders/is_object_legal_hold_enabled.rs rename to src/s3/builders/get_object_legal_hold.rs index 5313e65..dcd074b 100644 --- a/src/s3/builders/is_object_legal_hold_enabled.rs +++ b/src/s3/builders/get_object_legal_hold.rs @@ -16,14 +16,16 @@ use crate::s3::Client; use crate::s3::error::Error; use crate::s3::multimap::{Multimap, MultimapExt}; -use crate::s3::response::IsObjectLegalHoldEnabledResponse; +use crate::s3::response::GetObjectLegalHoldResponse; use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::utils::{check_bucket_name, check_object_name, insert}; use http::Method; -/// Argument builder for [is_object_legal_hold_enabled()](Client::is_object_legal_hold_enabled) API +/// 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. #[derive(Clone, Debug, Default)] -pub struct IsObjectLegalHoldEnabled { +pub struct GetObjectLegalHold { client: Client, extra_headers: Option, @@ -35,7 +37,7 @@ pub struct IsObjectLegalHoldEnabled { version_id: Option, } -impl IsObjectLegalHoldEnabled { +impl GetObjectLegalHold { pub fn new(client: Client, bucket: String, object: String) -> Self { Self { client, @@ -61,11 +63,11 @@ impl IsObjectLegalHoldEnabled { } } -impl S3Api for IsObjectLegalHoldEnabled { - type S3Response = IsObjectLegalHoldEnabledResponse; +impl S3Api for GetObjectLegalHold { + type S3Response = GetObjectLegalHoldResponse; } -impl ToS3Request for IsObjectLegalHoldEnabled { +impl ToS3Request for GetObjectLegalHold { fn to_s3request(self) -> Result { check_bucket_name(&self.bucket, true)?; check_object_name(&self.object)?; diff --git a/src/s3/builders/get_object_lock_config.rs b/src/s3/builders/get_object_lock_config.rs index e87f840..3095cf6 100644 --- a/src/s3/builders/get_object_lock_config.rs +++ b/src/s3/builders/get_object_lock_config.rs @@ -20,10 +20,12 @@ use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::utils::{check_bucket_name, insert}; use http::Method; -/// Argument builder for [get_object_lock_config()](Client::get_object_lock_config) API +/// 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. pub type GetObjectLockConfig = BucketCommon; -#[derive(Default, Debug)] +#[derive(Clone, Debug, Default)] pub struct GetObjectLockConfigPhantomData; impl S3Api for GetObjectLockConfig { diff --git a/src/s3/builders/object_prompt.rs b/src/s3/builders/get_object_prompt.rs similarity index 93% rename from src/s3/builders/object_prompt.rs rename to src/s3/builders/get_object_prompt.rs index efa1551..79ee312 100644 --- a/src/s3/builders/object_prompt.rs +++ b/src/s3/builders/get_object_prompt.rs @@ -20,7 +20,7 @@ use crate::s3::utils::{check_bucket_name, check_object_name}; use crate::s3::{ client::Client, error::Error, - response::ObjectPromptResponse, + response::GetObjectPromptResponse, types::{S3Api, S3Request, ToS3Request}, }; use bytes::Bytes; @@ -28,7 +28,7 @@ use http::Method; use serde_json::json; #[derive(Debug, Clone, Default)] -pub struct ObjectPrompt { +pub struct GetObjectPrompt { client: Client, bucket: String, object: String, @@ -43,9 +43,9 @@ pub struct ObjectPrompt { } // builder interface -impl ObjectPrompt { +impl GetObjectPrompt { pub fn new(client: Client, bucket: String, object: String, prompt: String) -> Self { - ObjectPrompt { + GetObjectPrompt { client, bucket, object, @@ -85,11 +85,11 @@ impl ObjectPrompt { } } -impl S3Api for ObjectPrompt { - type S3Response = ObjectPromptResponse; +impl S3Api for GetObjectPrompt { + type S3Response = GetObjectPromptResponse; } -impl ToS3Request for ObjectPrompt { +impl ToS3Request for GetObjectPrompt { fn to_s3request(self) -> Result { { check_bucket_name(&self.bucket, true)?; diff --git a/src/s3/builders/get_object_retention.rs b/src/s3/builders/get_object_retention.rs index 4f4bfc8..f2c7b37 100644 --- a/src/s3/builders/get_object_retention.rs +++ b/src/s3/builders/get_object_retention.rs @@ -21,7 +21,9 @@ use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::utils::{check_bucket_name, check_object_name, insert}; use http::Method; -/// Argument builder for [get_object_retention()](Client::get_object_retention) API +/// 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. #[derive(Clone, Debug, Default)] pub struct GetObjectRetention { client: Client, diff --git a/src/s3/builders/get_object_tags.rs b/src/s3/builders/get_object_tagging.rs similarity index 88% rename from src/s3/builders/get_object_tags.rs rename to src/s3/builders/get_object_tagging.rs index ef2db65..d283524 100644 --- a/src/s3/builders/get_object_tags.rs +++ b/src/s3/builders/get_object_tagging.rs @@ -16,14 +16,14 @@ use crate::s3::Client; use crate::s3::error::Error; use crate::s3::multimap::{Multimap, MultimapExt}; -use crate::s3::response::GetObjectTagsResponse; +use crate::s3::response::GetObjectTaggingResponse; use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::utils::{check_bucket_name, check_object_name, insert}; use http::Method; -/// Argument builder for [get_object_tags()](Client::get_object_tags) API +/// Argument builder for [get_object_tags()](crate::s3::client::Client::get_object_tagging) API #[derive(Clone, Debug, Default)] -pub struct GetObjectTags { +pub struct GetObjectTagging { client: Client, extra_headers: Option, @@ -35,7 +35,7 @@ pub struct GetObjectTags { version_id: Option, } -impl GetObjectTags { +impl GetObjectTagging { pub fn new(client: Client, bucket: String, object: String) -> Self { Self { client, @@ -66,11 +66,11 @@ impl GetObjectTags { } } -impl S3Api for GetObjectTags { - type S3Response = GetObjectTagsResponse; +impl S3Api for GetObjectTagging { + type S3Response = GetObjectTaggingResponse; } -impl ToS3Request for GetObjectTags { +impl ToS3Request for GetObjectTagging { fn to_s3request(self) -> Result { check_bucket_name(&self.bucket, true)?; check_object_name(&self.object)?; diff --git a/src/s3/builders/get_presigned_object_url.rs b/src/s3/builders/get_presigned_object_url.rs index 321a5f6..7978a5b 100644 --- a/src/s3/builders/get_presigned_object_url.rs +++ b/src/s3/builders/get_presigned_object_url.rs @@ -23,7 +23,7 @@ use crate::s3::signer::presign_v4; use crate::s3::utils::{UtcTime, check_bucket_name, check_object_name, utc_now}; use http::Method; -/// Argument for [get_presigned_object_url()](crate::s3::client::Client::get_presigned_object_url) API +/// This struct constructs the parameters required for the [`Client::get_presigned_object_url`](crate::s3::client::Client::get_presigned_object_url) method. #[derive(Clone, Debug, Default)] pub struct GetPresignedObjectUrl { client: Client, diff --git a/src/s3/builders/get_presigned_policy_form_data.rs b/src/s3/builders/get_presigned_policy_form_data.rs index a81c860..b2265a5 100644 --- a/src/s3/builders/get_presigned_policy_form_data.rs +++ b/src/s3/builders/get_presigned_policy_form_data.rs @@ -23,7 +23,7 @@ use crate::s3::utils::{ use serde_json::{Value, json}; use std::collections::HashMap; -/// Argument for [get_presigned_object_url()](crate::s3::client::Client::get_presigned_object_url) API +/// This struct constructs the parameters required for the [`Client::get_presigned_object_url`](crate::s3::client::Client::get_presigned_object_url) method. pub struct GetPresignedPolicyFormData { client: Client, policy: PostPolicy, @@ -54,6 +54,7 @@ impl GetPresignedPolicyFormData { /// /// Condition elements and respective condition for Post policy is available here. +#[derive(Clone, Debug, Default)] pub struct PostPolicy { pub region: Option, pub bucket: String, @@ -81,17 +82,13 @@ impl PostPolicy { /// let expiration = utc_now() + Duration::days(7); /// let policy = PostPolicy::new("bucket-name", expiration).unwrap(); /// ``` - pub fn new(bucket_name: &str, expiration: UtcTime) -> Result { + pub fn new(bucket_name: &str, expiration: UtcTime) -> Result { check_bucket_name(bucket_name, true)?; - Ok(PostPolicy { - region: None, + Ok(Self { bucket: bucket_name.to_owned(), expiration, - eq_conditions: HashMap::new(), - starts_with_conditions: HashMap::new(), - lower_limit: None, - upper_limit: None, + ..Default::default() }) } @@ -147,13 +144,12 @@ impl PostPolicy { || v.eq_ignore_ascii_case("content-length-range") { return Err(Error::PostPolicyError(format!( - "{} is unsupported for equals condition", - element + "{element} is unsupported for equals condition", ))); } if PostPolicy::is_reserved_element(v.as_str()) { - return Err(Error::PostPolicyError(format!("{} cannot set", element))); + return Err(Error::PostPolicyError(format!("{element} cannot set"))); } self.eq_conditions.insert(v, value.to_string()); @@ -203,13 +199,12 @@ impl PostPolicy { || (v.starts_with("x-amz-") && v.starts_with("x-amz-meta-")) { return Err(Error::PostPolicyError(format!( - "{} is unsupported for starts-with condition", - element + "{element} is unsupported for starts-with condition", ))); } if PostPolicy::is_reserved_element(v.as_str()) { - return Err(Error::PostPolicyError(format!("{} cannot set", element))); + return Err(Error::PostPolicyError(format!("{element} cannot set"))); } self.starts_with_conditions.insert(v, value.to_string()); diff --git a/src/s3/builders/get_region.rs b/src/s3/builders/get_region.rs index e542b40..b7589cb 100644 --- a/src/s3/builders/get_region.rs +++ b/src/s3/builders/get_region.rs @@ -22,7 +22,7 @@ use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::utils::{check_bucket_name, insert}; use http::Method; -/// Argument builder for [get_region()](Client::get_region) API +/// This struct constructs the parameters required for the [`Client::get_region`](crate::s3::client::Client::get_region) method. #[derive(Clone, Debug, Default)] pub struct GetRegion { client: Client, diff --git a/src/s3/builders/listen_bucket_notification.rs b/src/s3/builders/list_bucket_notification.rs similarity index 89% rename from src/s3/builders/listen_bucket_notification.rs rename to src/s3/builders/list_bucket_notification.rs index 8c1a8b2..f2f81d2 100644 --- a/src/s3/builders/listen_bucket_notification.rs +++ b/src/s3/builders/list_bucket_notification.rs @@ -1,5 +1,5 @@ // MinIO Rust Library for Amazon S3 Compatible Cloud Storage -// Copyright 2023 MinIO, Inc. +// 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. @@ -21,16 +21,16 @@ use crate::s3::multimap::{Multimap, MultimapExt}; use crate::s3::{ client::Client, error::Error, - response::ListenBucketNotificationResponse, + response::ListBucketNotificationResponse, types::{NotificationRecords, S3Api, S3Request, ToS3Request}, utils::check_bucket_name, }; /// Argument builder for -/// [listen_bucket_notification()](crate::s3::client::Client::listen_bucket_notification) +/// [listen_bucket_notification()](crate::s3::client::Client::list_bucket_notification) /// API. #[derive(Clone, Debug, Default)] -pub struct ListenBucketNotification { +pub struct ListBucketNotification { client: Client, extra_headers: Option, @@ -42,7 +42,7 @@ pub struct ListenBucketNotification { events: Option>, } -impl ListenBucketNotification { +impl ListBucketNotification { pub fn new(client: Client, bucket: String) -> Self { Self { client, @@ -83,19 +83,19 @@ impl ListenBucketNotification { } #[async_trait] -impl S3Api for ListenBucketNotification { +impl S3Api for ListBucketNotification { type S3Response = ( - ListenBucketNotificationResponse, + ListBucketNotificationResponse, Box> + Unpin + Send>, ); } -impl ToS3Request for ListenBucketNotification { +impl ToS3Request for ListBucketNotification { fn to_s3request(self) -> Result { { check_bucket_name(&self.bucket, true)?; if self.client.is_aws_host() { - return Err(Error::UnsupportedApi("ListenBucketNotification".into())); + return Err(Error::UnsupportedApi("ListBucketNotification".into())); } } diff --git a/src/s3/builders/list_buckets.rs b/src/s3/builders/list_buckets.rs index 22d47e3..de9733c 100644 --- a/src/s3/builders/list_buckets.rs +++ b/src/s3/builders/list_buckets.rs @@ -23,7 +23,9 @@ use crate::s3::{ types::{S3Api, S3Request, ToS3Request}, }; -/// Argument builder for [list_buckets()](Client::list_buckets) API. +/// 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. #[derive(Clone, Debug, Default)] pub struct ListBuckets { client: Client, diff --git a/src/s3/builders/list_objects.rs b/src/s3/builders/list_objects.rs index ef2b489..e93267a 100644 --- a/src/s3/builders/list_objects.rs +++ b/src/s3/builders/list_objects.rs @@ -57,7 +57,9 @@ fn delim_helper(delim: Option, recursive: bool) -> Option { // region: list-objects-v1 -/// Argument for ListObjectsV1 S3 API. +/// 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. #[derive(Clone, Debug, Default)] struct ListObjectsV1 { client: Client, @@ -157,7 +159,9 @@ impl From for ListObjectsV1 { // region: list-objects-v2 -/// Argument for ListObjectsV2 S3 API. +/// 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. #[derive(Clone, Debug, Default)] struct ListObjectsV2 { client: Client, @@ -174,7 +178,6 @@ struct ListObjectsV2 { continuation_token: Option, fetch_owner: bool, include_user_metadata: bool, - unsorted: bool, } #[async_trait] @@ -241,9 +244,6 @@ impl ToS3Request for ListObjectsV2 { if self.include_user_metadata { query_params.add("metadata", "true"); } - if self.unsorted { - query_params.add("unsorted", "true"); - } } Ok(S3Request::new(self.client, Method::GET) @@ -270,7 +270,6 @@ impl From for ListObjectsV2 { continuation_token: value.continuation_token, fetch_owner: value.fetch_owner, include_user_metadata: value.include_user_metadata, - unsorted: value.unsorted, } } } @@ -278,7 +277,9 @@ impl From for ListObjectsV2 { // region: list-object-versions -/// Argument for ListObjectVersions S3 API +/// 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. #[derive(Clone, Debug, Default)] struct ListObjectVersions { client: Client, @@ -294,7 +295,6 @@ struct ListObjectVersions { key_marker: Option, version_id_marker: Option, include_user_metadata: bool, - unsorted: bool, } #[async_trait] @@ -361,9 +361,6 @@ impl ToS3Request for ListObjectVersions { if self.include_user_metadata { query_params.add("metadata", "true"); } - if self.unsorted { - query_params.add("unsorted", "true"); - } } Ok(S3Request::new(self.client, Method::GET) @@ -389,7 +386,6 @@ impl From for ListObjectVersions { key_marker: value.key_marker, version_id_marker: value.version_id_marker, include_user_metadata: value.include_user_metadata, - unsorted: value.unsorted, } } } @@ -401,8 +397,8 @@ impl From for ListObjectVersions { /// Argument builder for /// [list_objects()](crate::s3::client::Client::list_objects) API. /// -/// 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 +/// 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 /// a stream of results. Pagination is automatically performed. #[derive(Clone, Debug, Default)] pub struct ListObjects { @@ -435,7 +431,6 @@ pub struct ListObjects { recursive: bool, use_api_v1: bool, include_versions: bool, - unsorted: bool, } #[async_trait] @@ -486,7 +481,7 @@ impl ListObjects { } /// Disable setting the `EncodingType` parameter in the ListObjects request. - /// By default it is set to `url`. + /// 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 @@ -552,6 +547,10 @@ impl ListObjects { } /// 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 @@ -563,11 +562,5 @@ impl ListObjects { self.include_versions = include_versions; self } - - /// Set this to allow unsorted versions. Defaults to false - pub fn unsorted(mut self, unsorted: bool) -> Self { - self.unsorted = unsorted; - self - } } // endregion: list-objects diff --git a/src/s3/builders/set_bucket_encryption.rs b/src/s3/builders/put_bucket_encryption.rs similarity index 87% rename from src/s3/builders/set_bucket_encryption.rs rename to src/s3/builders/put_bucket_encryption.rs index f12d0a2..0390853 100644 --- a/src/s3/builders/set_bucket_encryption.rs +++ b/src/s3/builders/put_bucket_encryption.rs @@ -16,16 +16,16 @@ use crate::s3::Client; use crate::s3::error::Error; use crate::s3::multimap::Multimap; -use crate::s3::response::SetBucketEncryptionResponse; +use crate::s3::response::PutBucketEncryptionResponse; use crate::s3::segmented_bytes::SegmentedBytes; use crate::s3::types::{S3Api, S3Request, SseConfig, ToS3Request}; use crate::s3::utils::{check_bucket_name, insert}; use bytes::Bytes; use http::Method; -/// Argument builder for [set_bucket_encryption()](Client::set_bucket_encryption) API +/// Argument builder for [put_bucket_encryption()](crate::s3::client::Client::put_bucket_encryption) API #[derive(Clone, Debug, Default)] -pub struct SetBucketEncryption { +pub struct PutBucketEncryption { client: Client, extra_headers: Option, @@ -36,7 +36,7 @@ pub struct SetBucketEncryption { config: SseConfig, } -impl SetBucketEncryption { +impl PutBucketEncryption { pub fn new(client: Client, bucket: String) -> Self { Self { client, @@ -66,11 +66,11 @@ impl SetBucketEncryption { } } -impl S3Api for SetBucketEncryption { - type S3Response = SetBucketEncryptionResponse; +impl S3Api for PutBucketEncryption { + type S3Response = PutBucketEncryptionResponse; } -impl ToS3Request for SetBucketEncryption { +impl ToS3Request for PutBucketEncryption { fn to_s3request(self) -> Result { check_bucket_name(&self.bucket, true)?; diff --git a/src/s3/builders/set_bucket_lifecycle.rs b/src/s3/builders/put_bucket_lifecycle.rs similarity index 88% rename from src/s3/builders/set_bucket_lifecycle.rs rename to src/s3/builders/put_bucket_lifecycle.rs index 2ba20e2..092c508 100644 --- a/src/s3/builders/set_bucket_lifecycle.rs +++ b/src/s3/builders/put_bucket_lifecycle.rs @@ -16,16 +16,16 @@ use crate::s3::Client; use crate::s3::error::Error; use crate::s3::multimap::{Multimap, MultimapExt}; -use crate::s3::response::SetBucketLifecycleResponse; +use crate::s3::response::PutBucketLifecycleResponse; use crate::s3::segmented_bytes::SegmentedBytes; use crate::s3::types::{LifecycleConfig, S3Api, S3Request, ToS3Request}; use crate::s3::utils::{check_bucket_name, insert, md5sum_hash}; use bytes::Bytes; use http::Method; -/// Argument builder for [set_bucket_lifecycle()](crate::s3::client::Client::set_bucket_lifecycle) API +/// Argument builder for [put_bucket_lifecycle()](crate::s3::client::Client::put_bucket_lifecycle) API #[derive(Clone, Debug, Default)] -pub struct SetBucketLifecycle { +pub struct PutBucketLifecycle { client: Client, extra_headers: Option, @@ -36,7 +36,7 @@ pub struct SetBucketLifecycle { config: LifecycleConfig, } -impl SetBucketLifecycle { +impl PutBucketLifecycle { pub fn new(client: Client, bucket: String) -> Self { Self { client, @@ -66,11 +66,11 @@ impl SetBucketLifecycle { } } -impl S3Api for SetBucketLifecycle { - type S3Response = SetBucketLifecycleResponse; +impl S3Api for PutBucketLifecycle { + type S3Response = PutBucketLifecycleResponse; } -impl ToS3Request for SetBucketLifecycle { +impl ToS3Request for PutBucketLifecycle { fn to_s3request(self) -> Result { check_bucket_name(&self.bucket, true)?; diff --git a/src/s3/builders/set_bucket_notification.rs b/src/s3/builders/put_bucket_notification.rs similarity index 80% rename from src/s3/builders/set_bucket_notification.rs rename to src/s3/builders/put_bucket_notification.rs index e9a98b2..3654175 100644 --- a/src/s3/builders/set_bucket_notification.rs +++ b/src/s3/builders/put_bucket_notification.rs @@ -16,16 +16,18 @@ use crate::s3::Client; use crate::s3::error::Error; use crate::s3::multimap::Multimap; -use crate::s3::response::SetBucketNotificationResponse; +use crate::s3::response::PutBucketNotificationResponse; use crate::s3::segmented_bytes::SegmentedBytes; use crate::s3::types::{NotificationConfig, S3Api, S3Request, ToS3Request}; use crate::s3::utils::{check_bucket_name, insert}; use bytes::Bytes; use http::Method; -/// Argument builder for [set_bucket_notification()](crate::s3::client::Client::set_bucket_notification) API +/// 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. #[derive(Clone, Debug, Default)] -pub struct SetBucketNotification { +pub struct PutBucketNotification { client: Client, extra_headers: Option, @@ -36,7 +38,7 @@ pub struct SetBucketNotification { config: NotificationConfig, } -impl SetBucketNotification { +impl PutBucketNotification { pub fn new(client: Client, bucket: String) -> Self { Self { client, @@ -66,11 +68,11 @@ impl SetBucketNotification { } } -impl S3Api for SetBucketNotification { - type S3Response = SetBucketNotificationResponse; +impl S3Api for PutBucketNotification { + type S3Response = PutBucketNotificationResponse; } -impl ToS3Request for SetBucketNotification { +impl ToS3Request for PutBucketNotification { fn to_s3request(self) -> Result { check_bucket_name(&self.bucket, true)?; diff --git a/src/s3/builders/set_bucket_policy.rs b/src/s3/builders/put_bucket_policy.rs similarity index 82% rename from src/s3/builders/set_bucket_policy.rs rename to src/s3/builders/put_bucket_policy.rs index ae1c5c9..c047abe 100644 --- a/src/s3/builders/set_bucket_policy.rs +++ b/src/s3/builders/put_bucket_policy.rs @@ -16,16 +16,18 @@ use crate::s3::Client; use crate::s3::error::Error; use crate::s3::multimap::Multimap; -use crate::s3::response::SetBucketPolicyResponse; +use crate::s3::response::PutBucketPolicyResponse; use crate::s3::segmented_bytes::SegmentedBytes; use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::utils::{check_bucket_name, insert}; use bytes::Bytes; use http::Method; -/// Argument builder for [set_bucket_policy()](crate::s3::client::Client::set_bucket_policy) API +/// 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. #[derive(Clone, Debug, Default)] -pub struct SetBucketPolicy { +pub struct PutBucketPolicy { client: Client, extra_headers: Option, @@ -36,7 +38,7 @@ pub struct SetBucketPolicy { config: String, //TODO consider PolicyConfig struct } -impl SetBucketPolicy { +impl PutBucketPolicy { pub fn new(client: Client, bucket: String) -> Self { Self { client, @@ -66,11 +68,11 @@ impl SetBucketPolicy { } } -impl S3Api for SetBucketPolicy { - type S3Response = SetBucketPolicyResponse; +impl S3Api for PutBucketPolicy { + type S3Response = PutBucketPolicyResponse; } -impl ToS3Request for SetBucketPolicy { +impl ToS3Request for PutBucketPolicy { fn to_s3request(self) -> Result { check_bucket_name(&self.bucket, true)?; diff --git a/src/s3/builders/set_bucket_replication.rs b/src/s3/builders/put_bucket_replication.rs similarity index 81% rename from src/s3/builders/set_bucket_replication.rs rename to src/s3/builders/put_bucket_replication.rs index 3a82292..0ba0bda 100644 --- a/src/s3/builders/set_bucket_replication.rs +++ b/src/s3/builders/put_bucket_replication.rs @@ -16,16 +16,18 @@ use crate::s3::Client; use crate::s3::error::Error; use crate::s3::multimap::Multimap; -use crate::s3::response::SetBucketReplicationResponse; +use crate::s3::response::PutBucketReplicationResponse; use crate::s3::segmented_bytes::SegmentedBytes; use crate::s3::types::{ReplicationConfig, S3Api, S3Request, ToS3Request}; use crate::s3::utils::{check_bucket_name, insert}; use bytes::Bytes; use http::Method; -/// Argument builder for [set_bucket_replication()](crate::s3::client::Client::set_bucket_replication) API +/// 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. #[derive(Clone, Debug, Default)] -pub struct SetBucketReplication { +pub struct PutBucketReplication { client: Client, extra_headers: Option, @@ -36,7 +38,7 @@ pub struct SetBucketReplication { config: ReplicationConfig, } -impl SetBucketReplication { +impl PutBucketReplication { pub fn new(client: Client, bucket: String) -> Self { Self { client, @@ -66,11 +68,11 @@ impl SetBucketReplication { } } -impl S3Api for SetBucketReplication { - type S3Response = SetBucketReplicationResponse; +impl S3Api for PutBucketReplication { + type S3Response = PutBucketReplicationResponse; } -impl ToS3Request for SetBucketReplication { +impl ToS3Request for PutBucketReplication { fn to_s3request(self) -> Result { check_bucket_name(&self.bucket, true)?; diff --git a/src/s3/builders/set_bucket_tags.rs b/src/s3/builders/put_bucket_tagging.rs similarity index 85% rename from src/s3/builders/set_bucket_tags.rs rename to src/s3/builders/put_bucket_tagging.rs index b2f1486..00d8849 100644 --- a/src/s3/builders/set_bucket_tags.rs +++ b/src/s3/builders/put_bucket_tagging.rs @@ -16,7 +16,7 @@ use crate::s3::Client; use crate::s3::error::Error; use crate::s3::multimap::Multimap; -use crate::s3::response::SetBucketTagsResponse; +use crate::s3::response::PutBucketTaggingResponse; use crate::s3::segmented_bytes::SegmentedBytes; use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::utils::{check_bucket_name, insert}; @@ -24,9 +24,11 @@ use bytes::Bytes; use http::Method; use std::collections::HashMap; -/// Argument builder for [set_bucket_tags()](crate::s3::client::Client::set_bucket_tags) API +/// 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. #[derive(Clone, Debug, Default)] -pub struct SetBucketTags { +pub struct PutBucketTagging { client: Client, extra_headers: Option, @@ -37,7 +39,7 @@ pub struct SetBucketTags { tags: HashMap, } -impl SetBucketTags { +impl PutBucketTagging { pub fn new(client: Client, bucket: String) -> Self { Self { client, @@ -67,11 +69,11 @@ impl SetBucketTags { } } -impl S3Api for SetBucketTags { - type S3Response = SetBucketTagsResponse; +impl S3Api for PutBucketTagging { + type S3Response = PutBucketTaggingResponse; } -impl ToS3Request for SetBucketTags { +impl ToS3Request for PutBucketTagging { fn to_s3request(self) -> Result { check_bucket_name(&self.bucket, true)?; diff --git a/src/s3/builders/set_bucket_versioning.rs b/src/s3/builders/put_bucket_versioning.rs similarity index 67% rename from src/s3/builders/set_bucket_versioning.rs rename to src/s3/builders/put_bucket_versioning.rs index f0fba37..83376b0 100644 --- a/src/s3/builders/set_bucket_versioning.rs +++ b/src/s3/builders/put_bucket_versioning.rs @@ -16,7 +16,7 @@ use crate::s3::Client; use crate::s3::error::Error; use crate::s3::multimap::Multimap; -use crate::s3::response::SetBucketVersioningResponse; +use crate::s3::response::PutBucketVersioningResponse; use crate::s3::segmented_bytes::SegmentedBytes; use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::utils::{check_bucket_name, insert}; @@ -24,11 +24,20 @@ use bytes::Bytes; use http::Method; use std::fmt; +/// Represents the versioning state of an S3 bucket. +/// +/// This enum corresponds to the possible values returned by the +/// `GetBucketVersioning` API call in S3-compatible services. +/// +/// # Variants +/// +/// - `Enabled`: Object versioning is enabled for the bucket. +/// - `Suspended`: Object versioning is suspended for the bucket. #[derive(Clone, Debug, PartialEq)] pub enum VersioningStatus { - /// **Enable** object versioning in given bucket. + /// Object versioning is enabled for the bucket. Enabled, - /// **Suspend** object versioning in given bucket. + /// Object versioning is suspended for the bucket. Suspended, } @@ -41,21 +50,42 @@ impl fmt::Display for VersioningStatus { } } -/// Argument builder for [set_bucket_encryption()](crate::s3::client::Client::set_bucket_encryption) API +/// 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. #[derive(Clone, Debug, Default)] -pub struct SetBucketVersioning { +pub struct PutBucketVersioning { + /// The S3 client instance used to send the request. client: Client, + /// Optional additional HTTP headers to include in the request. extra_headers: Option, + + /// Optional additional query parameters to include in the request URL. extra_query_params: Option, + + /// Optional AWS region to override the client's default region. region: Option, + + /// The name of the bucket for which to configure versioning. bucket: String, + /// Desired versioning status for the bucket. + /// + /// - `Some(VersioningStatus::Enabled)`: Enables versioning. + /// - `Some(VersioningStatus::Suspended)`: Suspends versioning. + /// - `None`: No change to the current versioning status. status: Option, + + /// Specifies whether MFA delete is enabled for the bucket. + /// + /// - `Some(true)`: Enables MFA delete. + /// - `Some(false)`: Disables MFA delete. + /// - `None`: No change to the current MFA delete setting. mfa_delete: Option, } -impl SetBucketVersioning { +impl PutBucketVersioning { pub fn new(client: Client, bucket: String) -> Self { Self { client, @@ -90,11 +120,11 @@ impl SetBucketVersioning { } } -impl S3Api for SetBucketVersioning { - type S3Response = SetBucketVersioningResponse; +impl S3Api for PutBucketVersioning { + type S3Response = PutBucketVersioningResponse; } -impl ToS3Request for SetBucketVersioning { +impl ToS3Request for PutBucketVersioning { fn to_s3request(self) -> Result { check_bucket_name(&self.bucket, true)?; diff --git a/src/s3/builders/put_object.rs b/src/s3/builders/put_object.rs index 7803cc3..8a51d7c 100644 --- a/src/s3/builders/put_object.rs +++ b/src/s3/builders/put_object.rs @@ -36,7 +36,7 @@ use std::{collections::HashMap, sync::Arc}; // region: multipart-upload /// Argument for -/// [create_multipart_upload()](Client::create_multipart_upload) +/// [create_multipart_upload()](crate::s3::client::Client::create_multipart_upload) /// API #[derive(Clone, Debug, Default)] pub struct CreateMultipartUpload { @@ -145,7 +145,7 @@ impl ToS3Request for CreateMultipartUpload { // region: abort-multipart-upload /// Argument for -/// [abort_multipart_upload()](Client::abort_multipart_upload) +/// [abort_multipart_upload()](crate::s3::client::Client::abort_multipart_upload) /// API #[derive(Clone, Debug, Default)] pub struct AbortMultipartUpload { @@ -214,7 +214,7 @@ impl ToS3Request for AbortMultipartUpload { // region: complete-multipart-upload /// Argument for -/// [complete_multipart_upload()](Client::complete_multipart_upload) +/// [complete_multipart_upload()](crate::s3::client::Client::complete_multipart_upload) /// API #[derive(Clone, Debug, Default)] pub struct CompleteMultipartUpload { @@ -317,7 +317,7 @@ impl ToS3Request for CompleteMultipartUpload { // region: upload-part -/// Argument for [upload_part()](Client::upload_part) S3 API +/// Argument for [upload_part()](crate::s3::client::Client::upload_part) S3 API #[derive(Debug, Clone, Default)] pub struct UploadPart { client: Client, @@ -417,8 +417,7 @@ impl ToS3Request for UploadPart { if let Some(part_number) = self.part_number { if !(1..=MAX_MULTIPART_COUNT).contains(&part_number) { return Err(Error::InvalidPartNumber(format!( - "part number must be between 1 and {}", - MAX_MULTIPART_COUNT + "part number must be between 1 and {MAX_MULTIPART_COUNT}" ))); } } @@ -530,6 +529,7 @@ impl ToS3Request for PutObject { /// PutObjectContent takes a `ObjectContent` stream and uploads it to MinIO/S3. /// /// It is a higher level API and handles multipart uploads transparently. +#[derive(Default)] pub struct PutObjectContent { client: Client, @@ -567,18 +567,7 @@ impl PutObjectContent { bucket, object, input_content: content.into(), - extra_headers: None, - extra_query_params: None, - region: None, - user_metadata: None, - sse: None, - tags: None, - retention: None, - legal_hold: false, - part_size: Size::Unknown, - content_type: None, - content_stream: ContentStream::empty(), - part_count: None, + ..Default::default() } } @@ -777,12 +766,7 @@ impl PutObjectContent { let buffer_size = part_content.len() as u64; total_read += buffer_size; - assert!( - buffer_size <= part_size, - "{:?} <= {:?}", - buffer_size, - part_size - ); + assert!(buffer_size <= part_size, "{buffer_size} <= {part_size}",); if (buffer_size == 0) && (part_number > 1) { // We are done as we uploaded at least 1 part and we have reached the end of the stream. @@ -897,8 +881,7 @@ fn into_headers_put_object( } if !k.starts_with("x-amz-meta-") { return Err(Error::InvalidUserMetadata(format!( - "user metadata key '{}' does not start with 'x-amz-meta-'", - k + "user metadata key '{k}' does not start with 'x-amz-meta-'", ))); } } @@ -941,10 +924,7 @@ fn into_headers_put_object( if !map.contains_key("Content-Type") { map.insert( "Content-Type".into(), - match content_type { - Some(content_type) => content_type.clone(), - None => "application/octet-stream".into(), - }, + content_type.unwrap_or_else(|| "application/octet-stream".into()), ); } diff --git a/src/s3/builders/enable_object_legal_hold.rs b/src/s3/builders/put_object_legal_hold.rs similarity index 70% rename from src/s3/builders/enable_object_legal_hold.rs rename to src/s3/builders/put_object_legal_hold.rs index 12ab0cd..52f6577 100644 --- a/src/s3/builders/enable_object_legal_hold.rs +++ b/src/s3/builders/put_object_legal_hold.rs @@ -16,16 +16,18 @@ use crate::s3::Client; use crate::s3::error::Error; use crate::s3::multimap::{Multimap, MultimapExt}; -use crate::s3::response::EnableObjectLegalHoldResponse; +use crate::s3::response::PutObjectLegalHoldResponse; use crate::s3::segmented_bytes::SegmentedBytes; use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::utils::{check_bucket_name, check_object_name, insert, md5sum_hash}; use bytes::Bytes; use http::Method; -/// Argument builder for [enable_object_legal_hold()](Client::enable_object_legal_hold) API +/// 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. #[derive(Clone, Debug, Default)] -pub struct EnableObjectLegalHold { +pub struct PutObjectLegalHold { client: Client, extra_headers: Option, @@ -35,9 +37,10 @@ pub struct EnableObjectLegalHold { object: String, version_id: Option, + legal_hold: Option, } -impl EnableObjectLegalHold { +impl PutObjectLegalHold { pub fn new(client: Client, bucket: String, object: String) -> Self { Self { client, @@ -61,13 +64,18 @@ impl EnableObjectLegalHold { self.version_id = version_id; self } + + pub fn legal_hold(mut self, legal_hold: Option) -> Self { + self.legal_hold = legal_hold; + self + } } -impl S3Api for EnableObjectLegalHold { - type S3Response = EnableObjectLegalHoldResponse; +impl S3Api for PutObjectLegalHold { + type S3Response = PutObjectLegalHoldResponse; } -impl ToS3Request for EnableObjectLegalHold { +impl ToS3Request for PutObjectLegalHold { fn to_s3request(self) -> Result { check_bucket_name(&self.bucket, true)?; check_object_name(&self.object)?; @@ -76,10 +84,14 @@ impl ToS3Request for EnableObjectLegalHold { let mut query_params: Multimap = insert(self.extra_query_params, "legal-hold"); query_params.add_version(self.version_id); - const PAYLOAD: &str = "ON"; - headers.add("Content-MD5", md5sum_hash(PAYLOAD.as_ref())); - let body: Option = Some(SegmentedBytes::from(Bytes::from(PAYLOAD))); - //TODO consider const body + let payload: &str = match self.legal_hold { + Some(true) => "ON", + _ => "OFF", + }; + // TODO consider const payload with precalculated md5 + + headers.add("Content-MD5", md5sum_hash(payload.as_ref())); + let body: Option = Some(SegmentedBytes::from(Bytes::from(payload))); Ok(S3Request::new(self.client, Method::PUT) .region(self.region) diff --git a/src/s3/builders/set_object_lock_config.rs b/src/s3/builders/put_object_lock_config.rs similarity index 81% rename from src/s3/builders/set_object_lock_config.rs rename to src/s3/builders/put_object_lock_config.rs index 14e088c..4b80116 100644 --- a/src/s3/builders/set_object_lock_config.rs +++ b/src/s3/builders/put_object_lock_config.rs @@ -16,17 +16,18 @@ use crate::s3::Client; use crate::s3::error::Error; use crate::s3::multimap::Multimap; -use crate::s3::response::SetObjectLockConfigResponse; +use crate::s3::response::PutObjectLockConfigResponse; use crate::s3::segmented_bytes::SegmentedBytes; use crate::s3::types::{ObjectLockConfig, S3Api, S3Request, ToS3Request}; use crate::s3::utils::{check_bucket_name, insert}; use bytes::Bytes; use http::Method; -/// Argument builder for [set_object_lock_config()](Client::set_object_lock_config) API - +/// 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. #[derive(Clone, Debug, Default)] -pub struct SetObjectLockConfig { +pub struct PutObjectLockConfig { client: Client, extra_headers: Option, @@ -37,7 +38,7 @@ pub struct SetObjectLockConfig { config: ObjectLockConfig, } -impl SetObjectLockConfig { +impl PutObjectLockConfig { pub fn new(client: Client, bucket: String) -> Self { Self { client, @@ -67,11 +68,11 @@ impl SetObjectLockConfig { } } -impl S3Api for SetObjectLockConfig { - type S3Response = SetObjectLockConfigResponse; +impl S3Api for PutObjectLockConfig { + type S3Response = PutObjectLockConfigResponse; } -impl ToS3Request for SetObjectLockConfig { +impl ToS3Request for PutObjectLockConfig { fn to_s3request(self) -> Result { check_bucket_name(&self.bucket, true)?; diff --git a/src/s3/builders/set_object_retention.rs b/src/s3/builders/put_object_retention.rs similarity index 88% rename from src/s3/builders/set_object_retention.rs rename to src/s3/builders/put_object_retention.rs index 848ad09..434fd54 100644 --- a/src/s3/builders/set_object_retention.rs +++ b/src/s3/builders/put_object_retention.rs @@ -16,7 +16,7 @@ use crate::s3::Client; use crate::s3::error::Error; use crate::s3::multimap::{Multimap, MultimapExt}; -use crate::s3::response::SetObjectRetentionResponse; +use crate::s3::response::PutObjectRetentionResponse; use crate::s3::segmented_bytes::SegmentedBytes; use crate::s3::types::{RetentionMode, S3Api, S3Request, ToS3Request}; use crate::s3::utils::{ @@ -25,9 +25,11 @@ use crate::s3::utils::{ use bytes::Bytes; use http::Method; -/// Argument builder for [set_object_retention()](Client::set_object_retention) API +/// 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. #[derive(Clone, Debug, Default)] -pub struct SetObjectRetention { +pub struct PutObjectRetention { client: Client, extra_headers: Option, @@ -42,7 +44,7 @@ pub struct SetObjectRetention { retain_until_date: Option, } -impl SetObjectRetention { +impl PutObjectRetention { pub fn new(client: Client, bucket: String, object: String) -> Self { Self { client, @@ -88,11 +90,11 @@ impl SetObjectRetention { } } -impl S3Api for SetObjectRetention { - type S3Response = SetObjectRetentionResponse; +impl S3Api for PutObjectRetention { + type S3Response = PutObjectRetentionResponse; } -impl ToS3Request for SetObjectRetention { +impl ToS3Request for PutObjectRetention { fn to_s3request(self) -> Result { { check_bucket_name(&self.bucket, true)?; diff --git a/src/s3/builders/set_object_tags.rs b/src/s3/builders/put_object_tagging.rs similarity index 91% rename from src/s3/builders/set_object_tags.rs rename to src/s3/builders/put_object_tagging.rs index 1ddebc7..2c9aec4 100644 --- a/src/s3/builders/set_object_tags.rs +++ b/src/s3/builders/put_object_tagging.rs @@ -16,7 +16,7 @@ use crate::s3::Client; use crate::s3::error::Error; use crate::s3::multimap::{Multimap, MultimapExt}; -use crate::s3::response::SetObjectTagsResponse; +use crate::s3::response::PutObjectTaggingResponse; use crate::s3::segmented_bytes::SegmentedBytes; use crate::s3::types::{S3Api, S3Request, ToS3Request}; use crate::s3::utils::{check_bucket_name, check_object_name, insert}; @@ -24,9 +24,9 @@ use bytes::Bytes; use http::Method; use std::collections::HashMap; -/// Argument builder for [set_object_tags()](Client::set_object_tags) API +/// Argument builder for [put_object_tagging()](crate::s3::client::Client::put_object_tagging) API #[derive(Clone, Debug, Default)] -pub struct SetObjectTags { +pub struct PutObjectTagging { client: Client, extra_headers: Option, @@ -39,7 +39,7 @@ pub struct SetObjectTags { tags: HashMap, } -impl SetObjectTags { +impl PutObjectTagging { pub fn new(client: Client, bucket: String, object: String) -> Self { Self { client, @@ -75,11 +75,11 @@ impl SetObjectTags { } } -impl S3Api for SetObjectTags { - type S3Response = SetObjectTagsResponse; +impl S3Api for PutObjectTagging { + type S3Response = PutObjectTaggingResponse; } -impl ToS3Request for SetObjectTags { +impl ToS3Request for PutObjectTagging { fn to_s3request(self) -> Result { check_bucket_name(&self.bucket, true)?; check_object_name(&self.object)?; diff --git a/src/s3/builders/select_object_content.rs b/src/s3/builders/select_object_content.rs index bf84ed2..90f8111 100644 --- a/src/s3/builders/select_object_content.rs +++ b/src/s3/builders/select_object_content.rs @@ -25,7 +25,9 @@ use async_trait::async_trait; use bytes::Bytes; use http::Method; -/// Argument builder for [bucket_exists()](Client::bucket_exists) API +/// 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. #[derive(Default)] pub struct SelectObjectContent { client: Client, diff --git a/src/s3/builders/stat_object.rs b/src/s3/builders/stat_object.rs index 0bf82c8..fde1834 100644 --- a/src/s3/builders/stat_object.rs +++ b/src/s3/builders/stat_object.rs @@ -27,7 +27,7 @@ use crate::s3::{ utils::{UtcTime, check_bucket_name, to_http_header_value}, }; -/// Argument builder for [list_objects()](Client::get_object) API. +/// This struct constructs the parameters required for the [`Client::stat_object`](crate::s3::client::Client::stat_object) method. #[derive(Debug, Clone, Default)] pub struct StatObject { client: Client, diff --git a/src/s3/client.rs b/src/s3/client.rs index 758d1e4..e793f05 100644 --- a/src/s3/client.rs +++ b/src/s3/client.rs @@ -43,50 +43,49 @@ use tokio::task; mod append_object; mod bucket_exists; mod copy_object; +mod create_bucket; +mod delete_bucket; mod delete_bucket_encryption; mod delete_bucket_lifecycle; mod delete_bucket_notification; mod delete_bucket_policy; mod delete_bucket_replication; -mod delete_bucket_tags; +mod delete_bucket_tagging; mod delete_object_lock_config; -mod delete_object_tags; -mod disable_object_legal_hold; -mod enable_object_legal_hold; +mod delete_object_tagging; +mod delete_objects; mod get_bucket_encryption; mod get_bucket_lifecycle; mod get_bucket_notification; mod get_bucket_policy; mod get_bucket_replication; -mod get_bucket_tags; +mod get_bucket_tagging; mod get_bucket_versioning; mod get_object; +mod get_object_legal_hold; mod get_object_lock_config; +mod get_object_prompt; mod get_object_retention; -mod get_object_tags; +mod get_object_tagging; mod get_presigned_object_url; mod get_presigned_post_form_data; mod get_region; -mod is_object_legal_hold_enabled; +mod list_bucket_notification; mod list_buckets; mod list_objects; -mod listen_bucket_notification; -mod make_bucket; -mod object_prompt; +mod put_bucket_encryption; +mod put_bucket_lifecycle; +mod put_bucket_notification; +mod put_bucket_policy; +mod put_bucket_replication; +mod put_bucket_tagging; +mod put_bucket_versioning; mod put_object; -mod remove_bucket; -mod remove_objects; +mod put_object_legal_hold; +mod put_object_lock_config; +mod put_object_retention; +mod put_object_tagging; mod select_object_content; -mod set_bucket_encryption; -mod set_bucket_lifecycle; -mod set_bucket_notification; -mod set_bucket_policy; -mod set_bucket_replication; -mod set_bucket_tags; -mod set_bucket_versioning; -mod set_object_lock_config; -mod set_object_retention; -mod set_object_tags; mod stat_object; use super::types::S3Api; @@ -252,7 +251,7 @@ impl Client { /// Returns whether this client is configured to use the express endpoint and is minio enterprise. pub fn is_minio_express(&self) -> bool { if self.shared.express.get().is_some() { - self.shared.express.get().unwrap().clone() + *self.shared.express.get().unwrap() } else { task::block_in_place(|| match tokio::runtime::Runtime::new() { Ok(rt) => { @@ -483,12 +482,8 @@ impl Client { // Sort headers alphabetically by name header_strings.sort(); - let body_str: String = String::from_utf8( - body.clone() - .unwrap_or(&SegmentedBytes::new()) - .to_bytes() - .to_vec(), - )?; + let body_str: String = + String::from_utf8(body.unwrap_or(&SegmentedBytes::new()).to_bytes().to_vec())?; println!( "S3 request: {} url={:?}; headers={:?}; body={}\n", @@ -535,15 +530,12 @@ impl Client { retry, ); - match e { - Error::S3Error(ref err) => { - if (err.code == ErrorCode::NoSuchBucket) || (err.code == ErrorCode::RetryHead) { - if let Some(v) = bucket_name { - self.shared.region_map.remove(v); - } + if let Error::S3Error(ref err) = e { + if (err.code == ErrorCode::NoSuchBucket) || (err.code == ErrorCode::RetryHead) { + if let Some(v) = bucket_name { + self.shared.region_map.remove(v); } } - _ => {} }; Err(e) @@ -700,12 +692,12 @@ impl SharedClientItems { 409 => match bucket_name { Some(_) => (ErrorCode::NoSuchBucket, "Bucket does not exist".into()), _ => ( - ErrorCode::ResourceConflict.into(), + ErrorCode::ResourceConflict, "Request resource conflicts".into(), ), }, 501 => ( - ErrorCode::MethodNotAllowed.into(), + ErrorCode::MethodNotAllowed, "The specified method is not allowed against this resource".into(), ), _ => return Error::ServerError(http_status_code), diff --git a/src/s3/client/append_object.rs b/src/s3/client/append_object.rs index 1192e1d..9189811 100644 --- a/src/s3/client/append_object.rs +++ b/src/s3/client/append_object.rs @@ -21,14 +21,41 @@ use crate::s3::builders::{AppendObject, AppendObjectContent}; use crate::s3::segmented_bytes::SegmentedBytes; impl Client { - /// Creates an 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. /// + /// To execute the request, call [`AppendObject::send()`](crate::s3::types::S3Api::send), + /// which returns a [`Result`] containing a [`AppendObjectResponse`](crate::s3::response::AppendObjectResponse). + /// /// 🛈 This operation is not supported for regular non-express buckets. - pub fn append_object, S2: Into>( + /// + /// # Example + /// + /// ```no_run + /// use minio::s3::Client; + /// use minio::s3::response::{AppendObjectResponse, PutObjectResponse}; + /// use minio::s3::segmented_bytes::SegmentedBytes; + /// use minio::s3::types::S3Api; + /// + /// #[tokio::main] + /// async fn main() { + /// let client: Client = Default::default(); // configure your client here + /// let data1: SegmentedBytes = SegmentedBytes::from("aaaa".to_string()); + /// let data2: SegmentedBytes = SegmentedBytes::from("bbbb".to_string()); + /// let resp: PutObjectResponse = client + /// .put_object("bucket-name", "object-name", data1) + /// .send().await.unwrap(); + /// let offset_bytes = 4; // the offset at which to append the data + /// let resp: AppendObjectResponse = client + /// .append_object("bucket-name", "object-name", data2, offset_bytes) + /// .send().await.unwrap(); + /// println!("size of the final object is {} bytes", resp.object_size); + /// } + /// ``` + pub fn append_object>( &self, - bucket: S1, - object: S2, + bucket: S, + object: S, data: SegmentedBytes, offset_bytes: u64, ) -> AppendObject { @@ -41,13 +68,42 @@ impl Client { ) } - /// 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) /// object. The content is streamed and appended to MinIO/S3. This is a higher-level API that /// handles multipart appends transparently. - pub fn append_object_content, S2: Into, C: Into>( + /// + /// To execute the request, call [`AppendObjectContent::send()`](crate::s3::types::S3Api::send), + /// which returns a [`Result`] containing a [`AppendObjectResponse`](crate::s3::response::AppendObjectResponse). + /// + /// 🛈 This operation is not supported for regular non-express buckets. + /// + /// # Example + /// + /// ```no_run + /// use minio::s3::Client; + /// use minio::s3::response::{AppendObjectResponse, PutObjectResponse}; + /// use minio::s3::builders::ObjectContent; + /// use minio::s3::segmented_bytes::SegmentedBytes; + /// use minio::s3::types::S3Api; + /// + /// #[tokio::main] + /// async fn main() { + /// let client: Client = Default::default(); // configure your client here + /// let data1: SegmentedBytes = SegmentedBytes::from("aaaa".to_string()); + /// let content2: String = "bbbb".to_string(); + /// let resp: PutObjectResponse = client + /// .put_object("bucket-name", "object-name", data1) + /// .send().await.unwrap(); + /// let resp: AppendObjectResponse = client + /// .append_object_content("bucket-name", "object-name", content2) + /// .send().await.unwrap(); + /// println!("size of the final object is {} bytes", resp.object_size); + /// } + /// ``` + pub fn append_object_content, C: Into>( &self, - bucket: S1, - object: S2, + bucket: S, + object: S, content: C, ) -> AppendObjectContent { AppendObjectContent::new(self.clone(), bucket.into(), object.into(), content) diff --git a/src/s3/client/bucket_exists.rs b/src/s3/client/bucket_exists.rs index e872125..f8d64da 100644 --- a/src/s3/client/bucket_exists.rs +++ b/src/s3/client/bucket_exists.rs @@ -31,12 +31,12 @@ impl Client { /// use minio::s3::response::BucketExistsResponse; /// use minio::s3::types::S3Api; /// - /// /// #[tokio::main] /// async fn main() { /// let client: Client = Default::default(); // configure your client here - /// let resp: BucketExistsResponse = - /// client.bucket_exists("bucket-name").send().await.unwrap(); + /// let resp: BucketExistsResponse = client + /// .bucket_exists("bucket-name") + /// .send().await.unwrap(); /// println!("bucket '{}' exists: {}", resp.bucket, resp.exists); /// } /// ``` diff --git a/src/s3/client/copy_object.rs b/src/s3/client/copy_object.rs index 413a79a..4a2203a 100644 --- a/src/s3/client/copy_object.rs +++ b/src/s3/client/copy_object.rs @@ -22,7 +22,31 @@ use crate::s3::builders::{ }; impl Client { - /// Executes [UploadPartCopy](https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html) S3 API + /// Creates a [`UploadPartCopy`] request builder. + /// See [UploadPartCopy](https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html) S3 API + /// + /// To execute the request, call [`UploadPartCopy::send()`](crate::s3::types::S3Api::send), + /// which returns a [`Result`] containing a [`UploadPartCopyResponse`](crate::s3::response::UploadPartCopyResponse). + /// + /// # Example + /// + /// ```no_run + /// use minio::s3::Client; + /// use minio::s3::response::{UploadPartCopyResponse}; + /// use minio::s3::segmented_bytes::SegmentedBytes; + /// use minio::s3::types::S3Api; + /// + /// #[tokio::main] + /// async fn main() { + /// let client: Client = Default::default(); // configure your client here + /// let data1: SegmentedBytes = SegmentedBytes::from("aaaa".to_string()); + /// todo!(); + /// let resp: UploadPartCopyResponse = client + /// .upload_part_copy("bucket-name", "object-name", "TODO") + /// .send().await.unwrap(); + /// println!("uploaded {}", resp.object); + /// } + /// ``` pub fn upload_part_copy, S2: Into, S3: Into>( &self, bucket: S1, @@ -34,7 +58,7 @@ impl Client { /// Create a CopyObject request builder. This is a lower-level API that /// performs a non-multipart object copy. - pub fn copy_object_internal, S2: Into>( + pub(crate) fn copy_object_internal, S2: Into>( &self, bucket: S1, object: S2, @@ -42,8 +66,8 @@ impl Client { CopyObjectInternal::new(self.clone(), bucket.into(), object.into()) } - /// copy object is a high-order API that calls [`stat_object`] and based on the results calls - /// either [`compose_object`] or [`copy_object_internal`] to copy the object. + /// copy object is a high-order API that calls [stat_object](Client::stat_object) and based on the results calls + /// either [compose_object](Client::compose_object) or [`copy_object_internal`](Client::copy_object_internal) to copy the object. pub fn copy_object, S2: Into>( &self, bucket: S1, @@ -60,8 +84,8 @@ impl Client { ComposeObjectInternal::new(self.clone(), bucket.into(), object.into()) } - /// compose object is high-order API that calls [`compose_object_internal`] and if that call fails, - /// it calls ['abort_multipart_upload`]. + /// compose object is high-order API that calls [`compose_object_internal`](Client::compose_object_internal) and if that call fails, + /// it calls ['abort_multipart_upload`](Client::abort_multipart_upload). pub fn compose_object, S2: Into>( &self, bucket: S1, diff --git a/src/s3/client/make_bucket.rs b/src/s3/client/create_bucket.rs similarity index 63% rename from src/s3/client/make_bucket.rs rename to src/s3/client/create_bucket.rs index e214ca1..2961d2b 100644 --- a/src/s3/client/make_bucket.rs +++ b/src/s3/client/create_bucket.rs @@ -16,31 +16,31 @@ //! S3 APIs for bucket objects. use super::Client; -use crate::s3::builders::MakeBucket; +use crate::s3::builders::CreateBucket; impl Client { - /// Creates a [`MakeBucket`] request builder. + /// Creates a [`CreateBucket`] request builder. /// - /// To execute the request, call [`MakeBucket::send()`](crate::s3::types::S3Api::send), - /// which returns a [`Result`] containing a [`MakeBucketResponse`](crate::s3::response::MakeBucketResponse). + /// To execute the request, call [`CreateBucket::send()`](crate::s3::types::S3Api::send), + /// which returns a [`Result`] containing a [`CreateBucketResponse`](crate::s3::response::CreateBucketResponse). /// /// # Example /// /// ```no_run /// use minio::s3::Client; - /// use minio::s3::response::MakeBucketResponse; + /// use minio::s3::response::CreateBucketResponse; /// use minio::s3::types::S3Api; /// - /// /// #[tokio::main] /// async fn main() { /// let client: Client = Default::default(); // configure your client here - /// let resp: MakeBucketResponse = - /// client.make_bucket("bucket-name").send().await.unwrap(); + /// let resp: CreateBucketResponse = client + /// .create_bucket("bucket-name") + /// .send().await.unwrap(); /// println!("Made bucket '{}' in region '{}'", resp.bucket, resp.region); /// } /// ``` - pub fn make_bucket>(&self, bucket: S) -> MakeBucket { - MakeBucket::new(self.clone(), bucket.into()) + pub fn create_bucket>(&self, bucket: S) -> CreateBucket { + CreateBucket::new(self.clone(), bucket.into()) } } diff --git a/src/s3/client/remove_bucket.rs b/src/s3/client/delete_bucket.rs similarity index 78% rename from src/s3/client/remove_bucket.rs rename to src/s3/client/delete_bucket.rs index a7abd2a..42efaaf 100644 --- a/src/s3/client/remove_bucket.rs +++ b/src/s3/client/delete_bucket.rs @@ -16,48 +16,46 @@ //! S3 APIs for bucket objects. use super::Client; -use crate::s3::builders::{ObjectToDelete, RemoveBucket, RemoveObject}; +use crate::s3::builders::{DeleteBucket, ObjectToDelete, RemoveObject}; use crate::s3::error::{Error, ErrorCode}; use crate::s3::response::DeleteResult; use crate::s3::response::{ - DisableObjectLegalHoldResponse, RemoveBucketResponse, RemoveObjectResponse, - RemoveObjectsResponse, + DeleteBucketResponse, PutObjectLegalHoldResponse, RemoveObjectResponse, RemoveObjectsResponse, }; use crate::s3::types::{S3Api, ToStream}; use futures::StreamExt; impl Client { - /// Creates a [`RemoveBucket`] request builder. + /// Creates a [`DeleteBucket`] request builder. /// - /// To execute the request, call [`RemoveBucket::send()`](crate::s3::types::S3Api::send), - /// which returns a [`Result`] containing a [`RemoveBucketResponse`](crate::s3::response::RemoveBucketResponse). + /// To execute the request, call [`DeleteBucket::send()`](crate::s3::types::S3Api::send), + /// which returns a [`Result`] containing a [`DeleteBucketResponse`]. /// /// # Example /// /// ```no_run /// use minio::s3::Client; - /// use minio::s3::response::RemoveBucketResponse; + /// use minio::s3::response::DeleteBucketResponse; /// use minio::s3::types::S3Api; /// - /// /// #[tokio::main] /// async fn main() { /// let client: Client = Default::default(); // configure your client here - /// let resp: RemoveBucketResponse = - /// client.remove_bucket("bucket-name").send().await.unwrap(); + /// let resp: DeleteBucketResponse = + /// client.delete_bucket("bucket-name").send().await.unwrap(); /// println!("bucket '{}' in region '{}' is removed", resp.bucket, resp.region); /// } /// ``` - pub fn remove_bucket>(&self, bucket: S) -> RemoveBucket { - RemoveBucket::new(self.clone(), bucket.into()) + pub fn delete_bucket>(&self, bucket: S) -> DeleteBucket { + DeleteBucket::new(self.clone(), bucket.into()) } - /// Removes a bucket and also removes non-empty buckets by first removing all objects before + /// Deletes a bucket and also deletes non-empty buckets by first removing all objects before /// deleting the bucket. Bypasses governance mode and legal hold. - pub async fn remove_and_purge_bucket>( + pub async fn delete_and_purge_bucket>( &self, bucket: S, - ) -> Result { + ) -> Result { let bucket: String = bucket.into(); if self.is_minio_express() { let mut stream = self.list_objects(&bucket).to_stream().await; @@ -98,8 +96,8 @@ impl Client { DeleteResult::Deleted(_) => {} DeleteResult::Error(v) => { // the object is not deleted. try to disable legal hold and try again. - let _resp: DisableObjectLegalHoldResponse = self - .disable_object_legal_hold(&bucket, &v.object_name) + let _resp: PutObjectLegalHoldResponse = self + .put_object_legal_hold(&bucket, &v.object_name, false) .version_id(v.version_id.clone()) .send() .await?; @@ -118,11 +116,11 @@ impl Client { } } } - match self.remove_bucket(bucket).send().await { + match self.delete_bucket(bucket).send().await { Ok(resp) => Ok(resp), Err(Error::S3Error(e)) => { if e.code == ErrorCode::NoSuchBucket { - Ok(RemoveBucketResponse { + Ok(DeleteBucketResponse { headers: e.headers, bucket: e.bucket_name, region: String::new(), diff --git a/src/s3/client/delete_bucket_encryption.rs b/src/s3/client/delete_bucket_encryption.rs index 874bdfa..68afd7a 100644 --- a/src/s3/client/delete_bucket_encryption.rs +++ b/src/s3/client/delete_bucket_encryption.rs @@ -31,12 +31,12 @@ impl Client { /// use minio::s3::response::DeleteBucketEncryptionResponse; /// use minio::s3::types::S3Api; /// - /// /// #[tokio::main] /// async fn main() { /// let client: Client = Default::default(); // configure your client here - /// let resp: DeleteBucketEncryptionResponse = - /// client.delete_bucket_encryption("bucket-name").send().await.unwrap(); + /// let resp: DeleteBucketEncryptionResponse = client + /// .delete_bucket_encryption("bucket-name") + /// .send().await.unwrap(); /// println!("bucket '{}' is deleted", resp.bucket); /// } /// ``` diff --git a/src/s3/client/delete_bucket_lifecycle.rs b/src/s3/client/delete_bucket_lifecycle.rs index 8fadd8f..2386c70 100644 --- a/src/s3/client/delete_bucket_lifecycle.rs +++ b/src/s3/client/delete_bucket_lifecycle.rs @@ -31,12 +31,12 @@ impl Client { /// use minio::s3::response::DeleteBucketLifecycleResponse; /// use minio::s3::types::S3Api; /// - /// /// #[tokio::main] /// async fn main() { /// let client: Client = Default::default(); // configure your client here - /// let resp: DeleteBucketLifecycleResponse = - /// client.delete_bucket_lifecycle("bucket-name").send().await.unwrap(); + /// let resp: DeleteBucketLifecycleResponse = client + /// .delete_bucket_lifecycle("bucket-name") + /// .send().await.unwrap(); /// println!("lifecycle of bucket '{}' is deleted", resp.bucket); /// } /// ``` diff --git a/src/s3/client/delete_bucket_notification.rs b/src/s3/client/delete_bucket_notification.rs index 36ca502..24995b0 100644 --- a/src/s3/client/delete_bucket_notification.rs +++ b/src/s3/client/delete_bucket_notification.rs @@ -31,12 +31,12 @@ impl Client { /// use minio::s3::response::DeleteBucketNotificationResponse; /// use minio::s3::types::S3Api; /// - /// /// #[tokio::main] /// async fn main() { /// let client: Client = Default::default(); // configure your client here - /// let resp: DeleteBucketNotificationResponse = - /// client.delete_bucket_notification("bucket-name").send().await.unwrap(); + /// let resp: DeleteBucketNotificationResponse = client + /// .delete_bucket_notification("bucket-name") + /// .send().await.unwrap(); /// println!("notification of bucket '{}' is deleted", resp.bucket); /// } /// ``` diff --git a/src/s3/client/delete_bucket_policy.rs b/src/s3/client/delete_bucket_policy.rs index d0da0b9..3e743ae 100644 --- a/src/s3/client/delete_bucket_policy.rs +++ b/src/s3/client/delete_bucket_policy.rs @@ -19,7 +19,6 @@ use super::Client; use crate::s3::builders::DeleteBucketPolicy; impl Client { - /// Create a DeleteBucketPolicy request builder. /// Creates a [`DeleteBucketPolicy`] request builder. /// /// To execute the request, call [`DeleteBucketPolicy::send()`](crate::s3::types::S3Api::send), @@ -32,12 +31,12 @@ impl Client { /// use minio::s3::response::DeleteBucketPolicyResponse; /// use minio::s3::types::S3Api; /// - /// /// #[tokio::main] /// async fn main() { /// let client: Client = Default::default(); // configure your client here - /// let resp: DeleteBucketPolicyResponse = - /// client.delete_bucket_policy("bucket-name").send().await.unwrap(); + /// let resp: DeleteBucketPolicyResponse = client + /// .delete_bucket_policy("bucket-name") + /// .send().await.unwrap(); /// println!("policy of bucket '{}' is deleted", resp.bucket); /// } /// ``` diff --git a/src/s3/client/delete_bucket_replication.rs b/src/s3/client/delete_bucket_replication.rs index 1ec32b1..0658059 100644 --- a/src/s3/client/delete_bucket_replication.rs +++ b/src/s3/client/delete_bucket_replication.rs @@ -33,12 +33,12 @@ impl Client { /// use minio::s3::response::DeleteBucketReplicationResponse; /// use minio::s3::types::S3Api; /// - /// /// #[tokio::main] /// async fn main() { /// let client: Client = Default::default(); // configure your client here - /// let resp: DeleteBucketReplicationResponse = - /// client.delete_bucket_replication("bucket-name").send().await.unwrap(); + /// let resp: DeleteBucketReplicationResponse = client + /// .delete_bucket_replication("bucket-name") + /// .send().await.unwrap(); /// println!("replication of bucket '{}' is deleted", resp.bucket); /// } /// ``` diff --git a/src/s3/client/delete_bucket_tags.rs b/src/s3/client/delete_bucket_tagging.rs similarity index 65% rename from src/s3/client/delete_bucket_tags.rs rename to src/s3/client/delete_bucket_tagging.rs index 62a2df2..ad22e0b 100644 --- a/src/s3/client/delete_bucket_tags.rs +++ b/src/s3/client/delete_bucket_tagging.rs @@ -16,13 +16,13 @@ //! S3 APIs for bucket objects. use super::Client; -use crate::s3::builders::DeleteBucketTags; +use crate::s3::builders::DeleteBucketTagging; impl Client { - /// Creates a [`DeleteBucketTags`] request builder. + /// Creates a [`DeleteBucketTagging`] request builder. /// - /// To execute the request, call [`DeleteBucketTagsResponse::send()`](crate::s3::types::S3Api::send), - /// which returns a [`Result`] containing a [`DeleteBucketTagsResponse`](crate::s3::response::DeleteBucketTagsResponse). + /// To execute the request, call [`DeleteBucketTagging::send()`](crate::s3::types::S3Api::send), + /// which returns a [`Result`] containing a [`DeleteBucketTagsResponse`](crate::s3::response::DeleteBucketTaggingResponse). /// /// 🛈 This operation is not supported for express buckets. /// @@ -30,19 +30,19 @@ impl Client { /// /// ```no_run /// use minio::s3::Client; - /// use minio::s3::response::DeleteBucketTagsResponse; + /// use minio::s3::response::DeleteBucketTaggingResponse; /// use minio::s3::types::S3Api; /// - /// /// #[tokio::main] /// async fn main() { /// let client: Client = Default::default(); // configure your client here - /// let resp: DeleteBucketTagsResponse = - /// client.delete_bucket_tags("bucket-name").send().await.unwrap(); + /// let resp: DeleteBucketTaggingResponse = client + /// .delete_bucket_tagging("bucket-name") + /// .send().await.unwrap(); /// println!("tags of bucket '{}' are deleted", resp.bucket); /// } /// ``` - pub fn delete_bucket_tags>(&self, bucket: S) -> DeleteBucketTags { - DeleteBucketTags::new(self.clone(), bucket.into()) + pub fn delete_bucket_tagging>(&self, bucket: S) -> DeleteBucketTagging { + DeleteBucketTagging::new(self.clone(), bucket.into()) } } diff --git a/src/s3/client/delete_object_lock_config.rs b/src/s3/client/delete_object_lock_config.rs index e8a1ce1..56192fb 100644 --- a/src/s3/client/delete_object_lock_config.rs +++ b/src/s3/client/delete_object_lock_config.rs @@ -30,24 +30,23 @@ impl Client { /// /// ```no_run /// use minio::s3::Client; - /// use minio::s3::response::{DeleteObjectLockConfigResponse, MakeBucketResponse, SetObjectLockConfigResponse}; + /// use minio::s3::response::{DeleteObjectLockConfigResponse, CreateBucketResponse, PutObjectLockConfigResponse}; /// use minio::s3::types::{S3Api, ObjectLockConfig, RetentionMode}; /// - /// /// #[tokio::main] /// async fn main() { /// let client: Client = Default::default(); // configure your client here /// let bucket_name = "bucket-name"; /// - /// let resp: MakeBucketResponse = - /// client.make_bucket(bucket_name).object_lock(true).send().await.unwrap(); + /// let resp: CreateBucketResponse = + /// client.create_bucket(bucket_name).object_lock(true).send().await.unwrap(); /// println!("created bucket '{}' with object locking enabled", resp.bucket); /// /// const DURATION_DAYS: i32 = 7; /// let config = ObjectLockConfig::new(RetentionMode::GOVERNANCE, Some(DURATION_DAYS), None).unwrap(); /// - /// let resp: SetObjectLockConfigResponse = - /// client.set_object_lock_config(bucket_name).config(config).send().await.unwrap(); + /// let resp: PutObjectLockConfigResponse = + /// client.put_object_lock_config(bucket_name).config(config).send().await.unwrap(); /// println!("configured object locking for bucket '{}'", resp.bucket); /// /// let resp: DeleteObjectLockConfigResponse = diff --git a/src/s3/client/delete_object_tags.rs b/src/s3/client/delete_object_tagging.rs similarity index 65% rename from src/s3/client/delete_object_tags.rs rename to src/s3/client/delete_object_tagging.rs index 3343254..91dcdaf 100644 --- a/src/s3/client/delete_object_tags.rs +++ b/src/s3/client/delete_object_tagging.rs @@ -16,13 +16,13 @@ //! S3 APIs for bucket objects. use super::Client; -use crate::s3::builders::DeleteObjectTags; +use crate::s3::builders::DeleteObjectTagging; impl Client { - /// Creates a [`DeleteObjectTags`] request builder. + /// Creates a [`DeleteObjectTagging`] request builder. /// - /// To execute the request, call [`DeleteObjectTags::send()`](crate::s3::types::S3Api::send), - /// which returns a [`Result`] containing a [`DeleteObjectTagsResponse`](crate::s3::response::DeleteObjectTagsResponse). + /// To execute the request, call [`DeleteObjectTagging::send()`](crate::s3::types::S3Api::send), + /// which returns a [`Result`] containing a [`DeleteObjectTagsResponse`](crate::s3::response::DeleteObjectTaggingResponse). /// /// 🛈 This operation is not supported for express buckets. /// @@ -30,23 +30,23 @@ impl Client { /// /// ```no_run /// use minio::s3::Client; - /// use minio::s3::response::DeleteObjectTagsResponse; + /// use minio::s3::response::DeleteObjectTaggingResponse; /// use minio::s3::types::S3Api; /// - /// /// #[tokio::main] /// async fn main() { /// let client: Client = Default::default(); // configure your client here - /// let resp: DeleteObjectTagsResponse = - /// client.delete_object_tags("bucket-name", "object_name").send().await.unwrap(); + /// let resp: DeleteObjectTaggingResponse = client + /// .delete_object_tagging("bucket-name", "object_name") + /// .send().await.unwrap(); /// println!("legal hold of object '{}' in bucket '{}' is deleted", resp.object, resp.bucket); /// } /// ``` - pub fn delete_object_tags, S2: Into>( + pub fn delete_object_tagging, S2: Into>( &self, bucket: S1, object: S2, - ) -> DeleteObjectTags { - DeleteObjectTags::new(self.clone(), bucket.into(), object.into()) + ) -> DeleteObjectTagging { + DeleteObjectTagging::new(self.clone(), bucket.into(), object.into()) } } diff --git a/src/s3/client/remove_objects.rs b/src/s3/client/delete_objects.rs similarity index 99% rename from src/s3/client/remove_objects.rs rename to src/s3/client/delete_objects.rs index fd43700..3fdc35d 100644 --- a/src/s3/client/remove_objects.rs +++ b/src/s3/client/delete_objects.rs @@ -35,7 +35,6 @@ impl Client { /// use minio::s3::builders::ObjectToDelete; /// use minio::s3::types::S3Api; /// - /// /// #[tokio::main] /// async fn main() { /// let client: Client = Default::default(); // configure your client here diff --git a/src/s3/client/get_bucket_encryption.rs b/src/s3/client/get_bucket_encryption.rs index 154f27b..a39d931 100644 --- a/src/s3/client/get_bucket_encryption.rs +++ b/src/s3/client/get_bucket_encryption.rs @@ -31,13 +31,13 @@ impl Client { /// use minio::s3::response::GetBucketEncryptionResponse; /// use minio::s3::types::S3Api; /// - /// /// #[tokio::main] /// async fn main() { /// let client: Client = Default::default(); // configure your client here - /// let resp: GetBucketEncryptionResponse = - /// client.get_bucket_encryption("bucket-name").send().await.unwrap(); - /// println!("retrieved SseConfig '{:?}' from bucket '{}' is enabled", resp.config, resp.bucket); + /// let resp: GetBucketEncryptionResponse = client + /// .get_bucket_encryption("bucket-name") + /// .send().await.unwrap(); + /// println!("retrieved SseConfig '{:?}' from bucket '{}'", resp.config, resp.bucket); /// } /// ``` pub fn get_bucket_encryption>(&self, bucket: S) -> GetBucketEncryption { diff --git a/src/s3/client/get_bucket_lifecycle.rs b/src/s3/client/get_bucket_lifecycle.rs index 7316bec..9325853 100644 --- a/src/s3/client/get_bucket_lifecycle.rs +++ b/src/s3/client/get_bucket_lifecycle.rs @@ -33,13 +33,13 @@ impl Client { /// use minio::s3::response::GetBucketLifecycleResponse; /// use minio::s3::types::S3Api; /// - /// /// #[tokio::main] /// async fn main() { /// let client: Client = Default::default(); // configure your client here - /// let resp: GetBucketLifecycleResponse = - /// client.get_bucket_lifecycle("bucket-name").send().await.unwrap(); - /// println!("retrieved bucket lifecycle config '{:?}' from bucket '{}' is enabled", resp.config, resp.bucket); + /// let resp: GetBucketLifecycleResponse = client + /// .get_bucket_lifecycle("bucket-name") + /// .send().await.unwrap(); + /// println!("retrieved bucket lifecycle config '{:?}' from bucket '{}'", resp.config, resp.bucket); /// } /// ``` pub fn get_bucket_lifecycle>(&self, bucket: S) -> GetBucketLifecycle { diff --git a/src/s3/client/get_bucket_notification.rs b/src/s3/client/get_bucket_notification.rs index d4295f2..e4befe8 100644 --- a/src/s3/client/get_bucket_notification.rs +++ b/src/s3/client/get_bucket_notification.rs @@ -31,13 +31,13 @@ impl Client { /// use minio::s3::response::GetBucketNotificationResponse; /// use minio::s3::types::S3Api; /// - /// /// #[tokio::main] /// async fn main() { /// let client: Client = Default::default(); // configure your client here - /// let resp: GetBucketNotificationResponse = - /// client.get_bucket_notification("bucket-name").send().await.unwrap(); - /// println!("retrieved bucket notification config '{:?}' from bucket '{}' is enabled", resp.config, resp.bucket); + /// let resp: GetBucketNotificationResponse = client + /// .get_bucket_notification("bucket-name") + /// .send().await.unwrap(); + /// println!("retrieved bucket notification config '{:?}' from bucket '{}'", resp.config, resp.bucket); /// } /// ``` pub fn get_bucket_notification>(&self, bucket: S) -> GetBucketNotification { diff --git a/src/s3/client/get_bucket_policy.rs b/src/s3/client/get_bucket_policy.rs index ed96f5a..3d605db 100644 --- a/src/s3/client/get_bucket_policy.rs +++ b/src/s3/client/get_bucket_policy.rs @@ -31,13 +31,13 @@ impl Client { /// use minio::s3::response::GetBucketPolicyResponse; /// use minio::s3::types::S3Api; /// - /// /// #[tokio::main] /// async fn main() { /// let client: Client = Default::default(); // configure your client here - /// let resp: GetBucketPolicyResponse = - /// client.get_bucket_policy("bucket-name").send().await.unwrap(); - /// println!("retrieved bucket policy config '{:?}' from bucket '{}' is enabled", resp.config, resp.bucket); + /// let resp: GetBucketPolicyResponse = client + /// .get_bucket_policy("bucket-name") + /// .send().await.unwrap(); + /// println!("retrieved bucket policy config '{:?}' from bucket '{}'", resp.config, resp.bucket); /// } /// ``` pub fn get_bucket_policy>(&self, bucket: S) -> GetBucketPolicy { diff --git a/src/s3/client/get_bucket_replication.rs b/src/s3/client/get_bucket_replication.rs index f24f536..cebedd9 100644 --- a/src/s3/client/get_bucket_replication.rs +++ b/src/s3/client/get_bucket_replication.rs @@ -33,13 +33,13 @@ impl Client { /// use minio::s3::response::GetBucketReplicationResponse; /// use minio::s3::types::S3Api; /// - /// /// #[tokio::main] /// async fn main() { /// let client: Client = Default::default(); // configure your client here - /// let resp: GetBucketReplicationResponse = - /// client.get_bucket_replication("bucket-name").send().await.unwrap(); - /// println!("retrieved bucket replication config '{:?}' from bucket '{}' is enabled", resp.config, resp.bucket); + /// let resp: GetBucketReplicationResponse = client + /// .get_bucket_replication("bucket-name") + /// .send().await.unwrap(); + /// println!("retrieved bucket replication config '{:?}' from bucket '{}'", resp.config, resp.bucket); /// } /// ``` pub fn get_bucket_replication>(&self, bucket: S) -> GetBucketReplication { diff --git a/src/s3/client/get_bucket_tags.rs b/src/s3/client/get_bucket_tagging.rs similarity index 70% rename from src/s3/client/get_bucket_tags.rs rename to src/s3/client/get_bucket_tagging.rs index 7e33e30..8071e72 100644 --- a/src/s3/client/get_bucket_tags.rs +++ b/src/s3/client/get_bucket_tagging.rs @@ -16,13 +16,13 @@ //! S3 APIs for bucket objects. use super::Client; -use crate::s3::builders::GetBucketTags; +use crate::s3::builders::GetBucketTagging; impl Client { - /// Creates a [`GetBucketTags`] request builder. + /// Creates a [`GetBucketTagging`] request builder. /// /// To execute the request, call [`GetBucketTags::send()`](crate::s3::types::S3Api::send), - /// which returns a [`Result`] containing a [`GetBucketTagsResponse`](crate::s3::response::GetBucketTagsResponse). + /// which returns a [`Result`] containing a [`GetBucketTagsResponse`](crate::s3::response::GetBucketTaggingResponse). /// /// 🛈 This operation is not supported for express buckets. /// @@ -30,19 +30,19 @@ impl Client { /// /// ```no_run /// use minio::s3::Client; - /// use minio::s3::response::GetBucketTagsResponse; + /// use minio::s3::response::GetBucketTaggingResponse; /// use minio::s3::types::S3Api; /// - /// /// #[tokio::main] /// async fn main() { /// let client: Client = Default::default(); // configure your client here - /// let resp: GetBucketTagsResponse = - /// client.get_bucket_tags("bucket-name").send().await.unwrap(); - /// println!("retrieved bucket tags '{:?}' from bucket '{}' is enabled", resp.tags, resp.bucket); + /// let resp: GetBucketTaggingResponse = client + /// .get_bucket_tagging("bucket-name") + /// .send().await.unwrap(); + /// println!("retrieved bucket tags '{:?}' from bucket '{}'", resp.tags, resp.bucket); /// } /// ``` - pub fn get_bucket_tags>(&self, bucket: S) -> GetBucketTags { - GetBucketTags::new(self.clone(), bucket.into()) + pub fn get_bucket_tagging>(&self, bucket: S) -> GetBucketTagging { + GetBucketTagging::new(self.clone(), bucket.into()) } } diff --git a/src/s3/client/get_bucket_versioning.rs b/src/s3/client/get_bucket_versioning.rs index aa0f2ce..ed893dd 100644 --- a/src/s3/client/get_bucket_versioning.rs +++ b/src/s3/client/get_bucket_versioning.rs @@ -33,13 +33,13 @@ impl Client { /// use minio::s3::response::GetBucketVersioningResponse; /// use minio::s3::types::S3Api; /// - /// /// #[tokio::main] /// async fn main() { /// let client: Client = Default::default(); // configure your client here - /// let resp: GetBucketVersioningResponse = - /// client.get_bucket_versioning("bucket-name").send().await.unwrap(); - /// println!("retrieved versioning status '{:?}' from bucket '{}' is enabled", resp.status, resp.bucket); + /// let resp: GetBucketVersioningResponse = client + /// .get_bucket_versioning("bucket-name") + /// .send().await.unwrap(); + /// println!("retrieved versioning status '{:?}' from bucket '{}'", resp.status, resp.bucket); /// } /// ``` pub fn get_bucket_versioning>(&self, bucket: S) -> GetBucketVersioning { diff --git a/src/s3/client/get_object.rs b/src/s3/client/get_object.rs index 4eda2b0..59209d4 100644 --- a/src/s3/client/get_object.rs +++ b/src/s3/client/get_object.rs @@ -31,12 +31,12 @@ impl Client { /// use minio::s3::response::GetObjectResponse; /// use minio::s3::types::S3Api; /// - /// /// #[tokio::main] /// async fn main() { /// let client: Client = Default::default(); // configure your client here - /// let resp: GetObjectResponse = - /// client.get_object("bucket-name", "object-name").send().await.unwrap(); + /// let resp: GetObjectResponse = client + /// .get_object("bucket-name", "object-name") + /// .send().await.unwrap(); /// let content_bytes = resp.content.to_segmented_bytes().await.unwrap().to_bytes(); /// let content_str = String::from_utf8(content_bytes.to_vec()).unwrap(); /// println!("retrieved content '{}'", content_str); diff --git a/src/s3/client/enable_object_legal_hold.rs b/src/s3/client/get_object_legal_hold.rs similarity index 60% rename from src/s3/client/enable_object_legal_hold.rs rename to src/s3/client/get_object_legal_hold.rs index a08f6bd..7693d3b 100644 --- a/src/s3/client/enable_object_legal_hold.rs +++ b/src/s3/client/get_object_legal_hold.rs @@ -16,13 +16,13 @@ //! S3 APIs for bucket objects. use super::Client; -use crate::s3::builders::EnableObjectLegalHold; +use crate::s3::builders::GetObjectLegalHold; impl Client { - /// Creates a [`EnableObjectLegalHold`] request builder. + /// Creates a [`GetObjectLegalHold`] request builder. /// - /// To execute the request, call [`EnableObjectLegalHold::send()`](crate::s3::types::S3Api::send), - /// which returns a [`Result`] containing a [`EnableObjectLegalHoldResponse`](crate::s3::response::EnableObjectLegalHoldResponse). + /// To execute the request, call [`GetObjectLegalHold::send()`](crate::s3::types::S3Api::send), + /// which returns a [`Result`] containing a [`GetObjectLegalHoldResponse`](crate::s3::response::GetObjectLegalHoldResponse). /// /// 🛈 This operation is not supported for express buckets. /// @@ -30,23 +30,23 @@ impl Client { /// /// ```no_run /// use minio::s3::Client; - /// use minio::s3::response::EnableObjectLegalHoldResponse; + /// use minio::s3::response::GetObjectLegalHoldResponse; /// use minio::s3::types::S3Api; /// - /// /// #[tokio::main] /// async fn main() { /// let client: Client = Default::default(); // configure your client here - /// let resp: EnableObjectLegalHoldResponse = - /// client.enable_object_legal_hold("bucket-name", "object-name").send().await.unwrap(); - /// println!("legal hold of object '{}' in bucket '{}' is enabled", resp.object, resp.bucket); + /// let resp: GetObjectLegalHoldResponse = client + /// .get_object_legal_hold("bucket-name", "object-name") + /// .send().await.unwrap(); + /// println!("legal hold of object '{}' in bucket '{}' is enabled: {}", resp.object, resp.bucket, resp.enabled); /// } /// ``` - pub fn enable_object_legal_hold, S2: Into>( + pub fn get_object_legal_hold, S2: Into>( &self, bucket: S1, object: S2, - ) -> EnableObjectLegalHold { - EnableObjectLegalHold::new(self.clone(), bucket.into(), object.into()) + ) -> GetObjectLegalHold { + GetObjectLegalHold::new(self.clone(), bucket.into(), object.into()) } } diff --git a/src/s3/client/get_object_lock_config.rs b/src/s3/client/get_object_lock_config.rs index 16183c2..d4e06f9 100644 --- a/src/s3/client/get_object_lock_config.rs +++ b/src/s3/client/get_object_lock_config.rs @@ -33,12 +33,12 @@ impl Client { /// use minio::s3::response::GetObjectLockConfigResponse; /// use minio::s3::types::S3Api; /// - /// /// #[tokio::main] /// async fn main() { /// let client: Client = Default::default(); // configure your client here - /// let resp: GetObjectLockConfigResponse = - /// client.get_object_lock_config("bucket-name").send().await.unwrap(); + /// let resp: GetObjectLockConfigResponse = client + /// .get_object_lock_config("bucket-name") + /// .send().await.unwrap(); /// println!("retrieved object lock config '{:?}' from bucket '{}' is enabled", resp.config, resp.bucket); /// } /// ``` diff --git a/src/s3/client/object_prompt.rs b/src/s3/client/get_object_prompt.rs similarity index 61% rename from src/s3/client/object_prompt.rs rename to src/s3/client/get_object_prompt.rs index 234e330..01a5ed1 100644 --- a/src/s3/client/object_prompt.rs +++ b/src/s3/client/get_object_prompt.rs @@ -15,39 +15,38 @@ //! S3 APIs for downloading objects. -use crate::s3::builders::ObjectPrompt; +use crate::s3::builders::GetObjectPrompt; use super::Client; impl Client { - /// Creates a [`ObjectPrompt`] request builder. Prompt an object using natural language. + /// Creates a [`GetObjectPrompt`] request builder. Prompt an object using natural language. /// - /// To execute the request, call [`ObjectPrompt::send()`](crate::s3::types::S3Api::send), - /// which returns a [`Result`] containing a [`ObjectPromptResponse`](crate::s3::response::ObjectPromptResponse). + /// To execute the request, call [`GetObjectPrompt::send()`](crate::s3::types::S3Api::send), + /// which returns a [`Result`] containing a [`GetObjectPromptResponse`](crate::s3::response::GetObjectPromptResponse). /// /// # Example /// /// ```no_run /// use minio::s3::Client; - /// use minio::s3::response::ObjectPromptResponse; + /// use minio::s3::response::GetObjectPromptResponse; /// use minio::s3::types::S3Api; /// - /// /// #[tokio::main] /// async fn main() { /// let client: Client = Default::default(); // configure your client here - /// let resp: ObjectPromptResponse = client - /// .object_prompt("bucket-name", "object-name", "What is it about?") + /// let resp: GetObjectPromptResponse = client + /// .get_object_prompt("bucket-name", "object-name", "What is it about?") /// .send().await.unwrap(); /// println!("the prompt response is: '{}'", resp.prompt_response); /// } /// ``` - pub fn object_prompt, S2: Into, S3: Into>( + pub fn get_object_prompt, S2: Into, S3: Into>( &self, bucket: S1, object: S2, prompt: S3, - ) -> ObjectPrompt { - ObjectPrompt::new(self.clone(), bucket.into(), object.into(), prompt.into()) + ) -> GetObjectPrompt { + GetObjectPrompt::new(self.clone(), bucket.into(), object.into(), prompt.into()) } } diff --git a/src/s3/client/get_object_retention.rs b/src/s3/client/get_object_retention.rs index 7b730a1..574e3d9 100644 --- a/src/s3/client/get_object_retention.rs +++ b/src/s3/client/get_object_retention.rs @@ -33,12 +33,12 @@ impl Client { /// use minio::s3::response::GetObjectRetentionResponse; /// use minio::s3::types::S3Api; /// - /// /// #[tokio::main] /// async fn main() { /// let client: Client = Default::default(); // configure your client here - /// let resp: GetObjectRetentionResponse = - /// client.get_object_retention("bucket-name", "object-name").send().await.unwrap(); + /// let resp: GetObjectRetentionResponse = client + /// .get_object_retention("bucket-name", "object-name") + /// .send().await.unwrap(); /// println!("retrieved retention mode '{:?}' until '{:?}' from bucket '{}' is enabled", resp.retention_mode, resp.retain_until_date, resp.bucket); /// } /// ``` diff --git a/src/s3/client/get_object_tags.rs b/src/s3/client/get_object_tagging.rs similarity index 64% rename from src/s3/client/get_object_tags.rs rename to src/s3/client/get_object_tagging.rs index 9a466f6..1332fad 100644 --- a/src/s3/client/get_object_tags.rs +++ b/src/s3/client/get_object_tagging.rs @@ -16,13 +16,13 @@ //! S3 APIs for bucket objects. use super::Client; -use crate::s3::builders::GetObjectTags; +use crate::s3::builders::GetObjectTagging; impl Client { - /// Creates a [`GetObjectTags`] request builder. + /// Creates a [`GetObjectTagging`] request builder. /// - /// To execute the request, call [`GetObjectTags::send()`](crate::s3::types::S3Api::send), - /// which returns a [`Result`] containing a [`GetObjectTagsResponse`](crate::s3::response::GetObjectTagsResponse). + /// To execute the request, call [`GetObjectTagging::send()`](crate::s3::types::S3Api::send), + /// which returns a [`Result`] containing a [`GetObjectTaggingResponse`](crate::s3::response::GetObjectTaggingResponse). /// /// 🛈 This operation is not supported for express buckets. /// @@ -30,23 +30,23 @@ impl Client { /// /// ```no_run /// use minio::s3::Client; - /// use minio::s3::response::GetObjectTagsResponse; + /// use minio::s3::response::GetObjectTaggingResponse; /// use minio::s3::types::S3Api; /// - /// /// #[tokio::main] /// async fn main() { /// let client: Client = Default::default(); // configure your client here - /// let resp: GetObjectTagsResponse = - /// client.get_object_tags("bucket-name", "object-name").send().await.unwrap(); + /// let resp: GetObjectTaggingResponse = client + /// .get_object_tagging("bucket-name", "object-name") + /// .send().await.unwrap(); /// println!("retrieved object tags '{:?}' from object '{}' in bucket '{}' is enabled", resp.tags, resp.object, resp.bucket); /// } /// ``` - pub fn get_object_tags, S2: Into>( + pub fn get_object_tagging, S2: Into>( &self, bucket: S1, object: S2, - ) -> GetObjectTags { - GetObjectTags::new(self.clone(), bucket.into(), object.into()) + ) -> GetObjectTagging { + GetObjectTagging::new(self.clone(), bucket.into(), object.into()) } } diff --git a/src/s3/client/get_presigned_object_url.rs b/src/s3/client/get_presigned_object_url.rs index eb8b6b9..7202c3c 100644 --- a/src/s3/client/get_presigned_object_url.rs +++ b/src/s3/client/get_presigned_object_url.rs @@ -18,10 +18,10 @@ use crate::s3::builders::GetPresignedObjectUrl; use http::Method; impl Client { - /// Creates a [`GetPresignedObjectURL`] request builder. + /// Creates a [`GetPresignedObjectUrl`] request builder. /// - /// To execute the request, call [`GetPresignedObjectURL::send()`](crate::s3::types::S3Api::send), - /// which returns a [`Result`] containing a [`GetPresignedObjectURLResponse`](crate::s3::response::GetPresignedObjectURLResponse). + /// To execute the request, call [`GetPresignedObjectUrl::send()`](crate::s3::types::S3Api::send), + /// which returns a [`Result`] containing a [`GetPresignedObjectUrlResponse`](crate::s3::response::GetPresignedObjectUrlResponse). /// /// # Example /// @@ -31,7 +31,6 @@ impl Client { /// use minio::s3::response::GetPresignedObjectUrlResponse; /// use minio::s3::types::S3Api; /// - /// /// #[tokio::main] /// async fn main() { /// let client: Client = Default::default(); // configure your client here diff --git a/src/s3/client/get_presigned_post_form_data.rs b/src/s3/client/get_presigned_post_form_data.rs index 8b4bd5e..02ce18e 100644 --- a/src/s3/client/get_presigned_post_form_data.rs +++ b/src/s3/client/get_presigned_post_form_data.rs @@ -17,18 +17,16 @@ use crate::s3::Client; use crate::s3::builders::{GetPresignedPolicyFormData, PostPolicy}; impl Client { - /// Create a GetPresignedPolicyFormData builder. /// Creates a [`GetPresignedPolicyFormData`] request builder. /// /// To execute the request, call [`GetPresignedPolicyFormData::send()`](crate::s3::types::S3Api::send), - /// which returns a [`Result`] containing a [`GetPresignedPolicyFormDataResponse`](crate::s3::response::GetPresignedPolicyFormDataResponse). + /// which returns a `HashMap` with the presigned policy. /// /// # Example /// /// ```no_run /// use http::Method; /// use std::collections::HashMap; - /// /// use chrono::{DateTime, Utc}; /// use minio::s3::Client; /// use minio::s3::types::S3Api; @@ -36,8 +34,7 @@ impl Client { /// use minio::s3::utils::utc_now; /// /// pub fn create_post_policy_example(bucket_name: &str, object_name: &str) -> PostPolicy { - /// let expiration: DateTime = utc_now() + chrono::Duration::days(5); - /// + /// let expiration: DateTime = utc_now() + chrono::Duration::days(5); /// let mut policy = PostPolicy::new(&bucket_name, expiration).unwrap(); /// policy.add_equals_condition("key", &object_name).unwrap(); /// policy @@ -50,7 +47,8 @@ impl Client { /// async fn main() { /// let client: Client = Default::default(); // configure your client here /// let policy: PostPolicy = create_post_policy_example("bucket-name", "object-name"); - /// let resp: HashMap = client.get_presigned_post_form_data(policy) + /// let resp: HashMap = client + /// .get_presigned_post_form_data(policy) /// .send().await.unwrap(); /// println!("presigned post form data: '{:?}'", resp); /// } diff --git a/src/s3/client/get_region.rs b/src/s3/client/get_region.rs index aad66b4..9204158 100644 --- a/src/s3/client/get_region.rs +++ b/src/s3/client/get_region.rs @@ -27,7 +27,7 @@ impl Client { /// Creates a [`GetRegion`] request builder. /// /// To execute the request, call [`GetRegion::send()`](crate::s3::types::S3Api::send), - /// which returns a [`Result`] containing a [`GetRegionResponse`](crate::s3::response::GetRegionResponse). + /// which returns a [`Result`] containing a [`GetRegionResponse`]. /// /// # Example /// @@ -36,12 +36,12 @@ impl Client { /// use minio::s3::response::GetRegionResponse; /// use minio::s3::types::S3Api; /// - /// /// #[tokio::main] /// async fn main() { /// let client: Client = Default::default(); // configure your client here - /// let resp: GetRegionResponse = - /// client.get_region("bucket-name").send().await.unwrap(); + /// let resp: GetRegionResponse = client + /// .get_region("bucket-name") + /// .send().await.unwrap(); /// println!("retrieved region '{:?}' for bucket '{}'", resp.region_response, resp.bucket); /// } /// ``` diff --git a/src/s3/client/is_object_legal_hold_enabled.rs b/src/s3/client/is_object_legal_hold_enabled.rs deleted file mode 100644 index f1cf991..0000000 --- a/src/s3/client/is_object_legal_hold_enabled.rs +++ /dev/null @@ -1,53 +0,0 @@ -// 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. - -//! S3 APIs for bucket objects. - -use super::Client; -use crate::s3::builders::IsObjectLegalHoldEnabled; - -impl Client { - /// Create a IsObjectLegalHoldEnabled request builder. - /// Creates a [`IsObjectLegalHoldEnabled`] request builder. - /// - /// To execute the request, call [`IsObjectLegalHoldEnabled::send()`](crate::s3::types::S3Api::send), - /// which returns a [`Result`] containing a [`IsObjectLegalHoldEnabledResponse`](crate::s3::response::IsObjectLegalHoldEnabledResponse). - /// - /// 🛈 This operation is not supported for express buckets. - /// - /// # Example - /// - /// ```no_run - /// use minio::s3::Client; - /// use minio::s3::response::IsObjectLegalHoldEnabledResponse; - /// use minio::s3::types::S3Api; - /// - /// - /// #[tokio::main] - /// async fn main() { - /// let client: Client = Default::default(); // configure your client here - /// let resp: IsObjectLegalHoldEnabledResponse = - /// client.is_object_legal_hold_enabled("bucket-name", "object-name").send().await.unwrap(); - /// println!("legal hold of object '{}' in bucket '{}' is enabled: {}", resp.object, resp.bucket, resp.enabled); - /// } - /// ``` - pub fn is_object_legal_hold_enabled, S2: Into>( - &self, - bucket: S1, - object: S2, - ) -> IsObjectLegalHoldEnabled { - IsObjectLegalHoldEnabled::new(self.clone(), bucket.into(), object.into()) - } -} diff --git a/src/s3/client/listen_bucket_notification.rs b/src/s3/client/list_bucket_notification.rs similarity index 76% rename from src/s3/client/listen_bucket_notification.rs rename to src/s3/client/list_bucket_notification.rs index 56cf799..749c166 100644 --- a/src/s3/client/listen_bucket_notification.rs +++ b/src/s3/client/list_bucket_notification.rs @@ -16,13 +16,13 @@ //! MinIO Extension API for S3 Buckets: ListenBucketNotification use super::Client; -use crate::s3::builders::ListenBucketNotification; +use crate::s3::builders::ListBucketNotification; impl Client { - /// Creates a [`ListenBucketNotification`] request builder. + /// Creates a [`ListBucketNotification`] request builder. /// - /// To execute the request, call [`ListenBucketNotification::send()`](crate::s3::types::S3Api::send), - /// which returns a tuple of [`ListenBucketNotificationResponse`](crate::s3::response::ListenBucketNotificationResponse) and a + /// To execute the request, call [`ListBucketNotification::send()`](crate::s3::types::S3Api::send), + /// which returns a tuple of [`ListBucketNotificationResponse`](crate::s3::response::ListBucketNotificationResponse) and a /// stream of [`NotificationRecords`](crate::s3::types::NotificationRecords). The former contains the HTTP headers /// returned by the server and the latter is a stream of notification /// records. In normal operation (when there are no errors), the stream @@ -39,12 +39,11 @@ impl Client { /// use minio::s3::types::{NotificationRecord, NotificationRecords, S3Api}; /// use futures_util::StreamExt; /// - /// /// #[tokio::main] /// async fn main() { /// let client: Client = Default::default(); // configure your client here /// let (_resp, mut event_stream) = client - /// .listen_bucket_notification("bucket-name") + /// .list_bucket_notification("bucket-name") /// .send().await .unwrap(); /// /// while let Some(event) = event_stream.next().await { @@ -54,10 +53,7 @@ impl Client { /// } /// } /// ``` - pub fn listen_bucket_notification>( - &self, - bucket: S, - ) -> ListenBucketNotification { - ListenBucketNotification::new(self.clone(), bucket.into()) + pub fn list_bucket_notification>(&self, bucket: S) -> ListBucketNotification { + ListBucketNotification::new(self.clone(), bucket.into()) } } diff --git a/src/s3/client/list_buckets.rs b/src/s3/client/list_buckets.rs index 957b052..fe0f4d8 100644 --- a/src/s3/client/list_buckets.rs +++ b/src/s3/client/list_buckets.rs @@ -32,12 +32,12 @@ impl Client { /// use minio::s3::types::S3Api; /// use std::sync::Arc; /// - /// /// #[tokio::main] /// async fn main() { /// let client: Client = Default::default(); // configure your client here - /// let resp: ListBucketsResponse = - /// client.list_buckets().send().await.unwrap(); + /// let resp: ListBucketsResponse = client + /// .list_buckets() + /// .send().await.unwrap(); /// println!("retrieved buckets '{:?}'", resp.buckets); /// } /// ``` diff --git a/src/s3/client/put_bucket_encryption.rs b/src/s3/client/put_bucket_encryption.rs new file mode 100644 index 0000000..12c20bf --- /dev/null +++ b/src/s3/client/put_bucket_encryption.rs @@ -0,0 +1,51 @@ +// 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. + +//! S3 APIs for bucket objects. + +use super::Client; +use crate::s3::builders::PutBucketEncryption; + +impl Client { + /// Creates a [`PutBucketEncryption`] request builder. + /// + /// To execute the request, call [`SetBucketEncryption::send()`](crate::s3::types::S3Api::send), + /// which returns a [`Result`] containing a [`SetBucketEncryptionResponse`](crate::s3::response::PutBucketEncryptionResponse). + /// + /// 🛈 This operation is not supported for express buckets. + /// + /// # Example + /// + /// ```no_run + /// use minio::s3::types::SseConfig; + /// use minio::s3::Client; + /// use minio::s3::response::PutBucketEncryptionResponse; + /// use minio::s3::types::S3Api; + /// + /// #[tokio::main] + /// async fn main() { + /// let client: Client = Default::default(); // configure your client here + /// let config = SseConfig::default(); + /// let resp: PutBucketEncryptionResponse = client + /// .put_bucket_encryption("bucket-name") + /// .sse_config(config) + /// .send().await.unwrap(); + /// println!("set encryption on bucket '{}'", resp.bucket); + /// } + /// ``` + pub fn put_bucket_encryption>(&self, bucket: S) -> PutBucketEncryption { + PutBucketEncryption::new(self.clone(), bucket.into()) + } +} diff --git a/src/s3/client/set_bucket_lifecycle.rs b/src/s3/client/put_bucket_lifecycle.rs similarity index 82% rename from src/s3/client/set_bucket_lifecycle.rs rename to src/s3/client/put_bucket_lifecycle.rs index b66eed1..aa71c41 100644 --- a/src/s3/client/set_bucket_lifecycle.rs +++ b/src/s3/client/put_bucket_lifecycle.rs @@ -16,24 +16,23 @@ //! S3 APIs for bucket objects. use super::Client; -use crate::s3::builders::SetBucketLifecycle; +use crate::s3::builders::PutBucketLifecycle; impl Client { - /// Creates a [`SetBucketLifecycle`] request builder. + /// Creates a [`PutBucketLifecycle`] request builder. /// /// To execute the request, call [`SetBucketLifecycle::send()`](crate::s3::types::S3Api::send), - /// which returns a [`Result`] containing a [`SetBucketLifecycleResponse`](crate::s3::response::SetBucketLifecycleResponse). + /// which returns a [`Result`] containing a [`SetBucketLifecycleResponse`](crate::s3::response::PutBucketLifecycleResponse). /// /// # Example /// /// ```no_run + /// use std::collections::HashMap; /// use minio::s3::Client; /// use minio::s3::builders::VersioningStatus; - /// use minio::s3::response::SetBucketLifecycleResponse; + /// use minio::s3::response::PutBucketLifecycleResponse; /// use minio::s3::types::{Filter, LifecycleConfig, LifecycleRule, S3Api}; /// - /// use std::collections::HashMap; - /// /// #[tokio::main] /// async fn main() { /// let client: Client = Default::default(); // configure your client here @@ -54,14 +53,14 @@ impl Client { /// transition_storage_class: None, /// }]; /// - /// let resp: SetBucketLifecycleResponse = client - /// .set_bucket_lifecycle("bucket-name") + /// let resp: PutBucketLifecycleResponse = client + /// .put_bucket_lifecycle("bucket-name") /// .life_cycle_config(LifecycleConfig { rules }) /// .send().await.unwrap(); /// println!("set bucket replication policy on bucket '{}'", resp.bucket); /// } /// ``` - pub fn set_bucket_lifecycle>(&self, bucket: S) -> SetBucketLifecycle { - SetBucketLifecycle::new(self.clone(), bucket.into()) + pub fn put_bucket_lifecycle>(&self, bucket: S) -> PutBucketLifecycle { + PutBucketLifecycle::new(self.clone(), bucket.into()) } } diff --git a/src/s3/client/set_bucket_notification.rs b/src/s3/client/put_bucket_notification.rs similarity index 81% rename from src/s3/client/set_bucket_notification.rs rename to src/s3/client/put_bucket_notification.rs index 0a38729..4a57f92 100644 --- a/src/s3/client/set_bucket_notification.rs +++ b/src/s3/client/put_bucket_notification.rs @@ -16,21 +16,20 @@ //! S3 APIs for bucket objects. use super::Client; -use crate::s3::builders::SetBucketNotification; +use crate::s3::builders::PutBucketNotification; impl Client { - /// Creates a [`SetBucketNotification`] request builder. + /// Creates a [`PutBucketNotification`] request builder. /// /// To execute the request, call [`SetBucketNotification::send()`](crate::s3::types::S3Api::send), - /// which returns a [`Result`] containing a [`SetBucketNotificationResponse`](crate::s3::response::SetBucketNotificationResponse). + /// which returns a [`Result`] containing a [`SetBucketNotificationResponse`](crate::s3::response::PutBucketNotificationResponse). /// /// # Example /// /// ```no_run /// use minio::s3::Client; /// use minio::s3::types::{NotificationConfig, PrefixFilterRule, QueueConfig, S3Api, SuffixFilterRule}; - /// use minio::s3::response::SetBucketNotificationResponse; - /// + /// use minio::s3::response::PutBucketNotificationResponse; /// /// #[tokio::main] /// async fn main() { @@ -55,14 +54,14 @@ impl Client { /// topic_config_list: None, /// }; /// - /// let resp: SetBucketNotificationResponse = client - /// .set_bucket_notification("bucket-name") + /// let resp: PutBucketNotificationResponse = client + /// .put_bucket_notification("bucket-name") /// .notification_config(config) /// .send().await.unwrap(); /// println!("set bucket notification for bucket '{:?}'", resp.bucket); /// } /// ``` - pub fn set_bucket_notification>(&self, bucket: S) -> SetBucketNotification { - SetBucketNotification::new(self.clone(), bucket.into()) + pub fn put_bucket_notification>(&self, bucket: S) -> PutBucketNotification { + PutBucketNotification::new(self.clone(), bucket.into()) } } diff --git a/src/s3/client/set_bucket_policy.rs b/src/s3/client/put_bucket_policy.rs similarity index 82% rename from src/s3/client/set_bucket_policy.rs rename to src/s3/client/put_bucket_policy.rs index 997f11a..ca3e404 100644 --- a/src/s3/client/set_bucket_policy.rs +++ b/src/s3/client/put_bucket_policy.rs @@ -16,24 +16,23 @@ //! S3 APIs for bucket objects. use super::Client; -use crate::s3::builders::SetBucketPolicy; +use crate::s3::builders::PutBucketPolicy; impl Client { - /// Creates a [`SetBucketPolicy`] request builder. + /// Creates a [`PutBucketPolicy`] request builder. /// /// To execute the request, call [`SetBucketPolicy::send()`](crate::s3::types::S3Api::send), - /// which returns a [`Result`] containing a [`SetBucketPolicyResponse`](crate::s3::response::SetBucketPolicyResponse). + /// which returns a [`Result`] containing a [`SetBucketPolicyResponse`](crate::s3::response::PutBucketPolicyResponse). /// /// # Example /// /// ```no_run + /// use std::collections::HashMap; /// use minio::s3::Client; /// use minio::s3::builders::VersioningStatus; - /// use minio::s3::response::SetBucketPolicyResponse; + /// use minio::s3::response::PutBucketPolicyResponse; /// use minio::s3::types::{S3Api, AndOperator, Destination, Filter, ReplicationConfig, ReplicationRule}; /// - /// use std::collections::HashMap; - /// /// #[tokio::main] /// async fn main() { /// let client: Client = Default::default(); // configure your client here @@ -62,14 +61,14 @@ impl Client { /// }] /// }"#; /// - /// let resp: SetBucketPolicyResponse = client - /// .set_bucket_policy("bucket-name") + /// let resp: PutBucketPolicyResponse = client + /// .put_bucket_policy("bucket-name") /// .config(config.to_owned()) /// .send().await.unwrap(); /// println!("set bucket replication policy on bucket '{}'", resp.bucket); /// } /// ``` - pub fn set_bucket_policy>(&self, bucket: S) -> SetBucketPolicy { - SetBucketPolicy::new(self.clone(), bucket.into()) + pub fn put_bucket_policy>(&self, bucket: S) -> PutBucketPolicy { + PutBucketPolicy::new(self.clone(), bucket.into()) } } diff --git a/src/s3/client/set_bucket_replication.rs b/src/s3/client/put_bucket_replication.rs similarity index 82% rename from src/s3/client/set_bucket_replication.rs rename to src/s3/client/put_bucket_replication.rs index 01bb7b5..9e39e18 100644 --- a/src/s3/client/set_bucket_replication.rs +++ b/src/s3/client/put_bucket_replication.rs @@ -16,13 +16,13 @@ //! S3 APIs for bucket objects. use super::Client; -use crate::s3::builders::SetBucketReplication; +use crate::s3::builders::PutBucketReplication; impl Client { - /// Creates a [`SetBucketReplication`] request builder. + /// Creates a [`PutBucketReplication`] request builder. /// /// To execute the request, call [`SetBucketReplication::send()`](crate::s3::types::S3Api::send), - /// which returns a [`Result`] containing a [`SetBucketReplicationResponse`](crate::s3::response::SetBucketReplicationResponse). + /// which returns a [`Result`] containing a [`SetBucketReplicationResponse`](crate::s3::response::PutBucketReplicationResponse). /// /// 🛈 This operation is not supported for express buckets. /// @@ -31,7 +31,7 @@ impl Client { /// ```no_run /// use minio::s3::Client; /// use minio::s3::builders::VersioningStatus; - /// use minio::s3::response::SetBucketReplicationResponse; + /// use minio::s3::response::PutBucketReplicationResponse; /// use minio::s3::types::{S3Api, AndOperator, Destination, Filter, ReplicationConfig, ReplicationRule}; /// /// use std::collections::HashMap; @@ -59,8 +59,8 @@ impl Client { /// existing_object_replication_status: None, /// filter: Some(Filter { /// and_operator: Some(AndOperator { - /// prefix: Some(String::from("TaxDocs")), - /// tags: Some(tags), + /// prefix: Some(String::from("TaxDocs")), + /// tags: Some(tags), /// }), /// prefix: None, /// tag: None, @@ -73,14 +73,14 @@ impl Client { /// status: true, /// }); /// - /// let resp: SetBucketReplicationResponse = client - /// .set_bucket_replication("bucket-name") + /// let resp: PutBucketReplicationResponse = client + /// .put_bucket_replication("bucket-name") /// .replication_config(ReplicationConfig {role: None, rules}) /// .send().await.unwrap(); /// println!("enabled versioning on bucket '{}'", resp.bucket); /// } /// ``` - pub fn set_bucket_replication>(&self, bucket: S) -> SetBucketReplication { - SetBucketReplication::new(self.clone(), bucket.into()) + pub fn put_bucket_replication>(&self, bucket: S) -> PutBucketReplication { + PutBucketReplication::new(self.clone(), bucket.into()) } } diff --git a/src/s3/client/set_bucket_tags.rs b/src/s3/client/put_bucket_tagging.rs similarity index 70% rename from src/s3/client/set_bucket_tags.rs rename to src/s3/client/put_bucket_tagging.rs index f6fab66..2d2ad21 100644 --- a/src/s3/client/set_bucket_tags.rs +++ b/src/s3/client/put_bucket_tagging.rs @@ -16,13 +16,13 @@ //! S3 APIs for bucket objects. use super::Client; -use crate::s3::builders::SetBucketTags; +use crate::s3::builders::PutBucketTagging; impl Client { - /// Creates a [`SetBucketTags`] request builder. + /// Creates a [`PutBucketTagging`] request builder. /// - /// To execute the request, call [`SetBucketTags::send()`](crate::s3::types::S3Api::send), - /// which returns a [`Result`] containing a [`SetBucketTagsResponse`](crate::s3::response::SetBucketTagsResponse). + /// To execute the request, call [`PutBucketTagging::send()`](crate::s3::types::S3Api::send), + /// which returns a [`Result`] containing a [`PutBucketTaggingResponse`](crate::s3::response::PutBucketTaggingResponse). /// /// 🛈 This operation is not supported for express buckets. /// @@ -31,7 +31,7 @@ impl Client { /// ```no_run /// use minio::s3::Client; /// use minio::s3::builders::VersioningStatus; - /// use minio::s3::response::SetBucketTagsResponse; + /// use minio::s3::response::PutBucketTaggingResponse; /// use minio::s3::types::S3Api; /// /// use std::collections::HashMap; @@ -44,14 +44,14 @@ impl Client { /// tags.insert(String::from("Project"), String::from("Project One")); /// tags.insert(String::from("User"), String::from("jsmith")); /// - /// let resp: SetBucketTagsResponse = client - /// .set_bucket_tags("bucket-name") + /// let resp: PutBucketTaggingResponse = client + /// .put_bucket_tagging("bucket-name") /// .tags(tags) /// .send().await.unwrap(); /// println!("set tags on bucket '{}'", resp.bucket); /// } /// ``` - pub fn set_bucket_tags>(&self, bucket: S) -> SetBucketTags { - SetBucketTags::new(self.clone(), bucket.into()) + pub fn put_bucket_tagging>(&self, bucket: S) -> PutBucketTagging { + PutBucketTagging::new(self.clone(), bucket.into()) } } diff --git a/src/s3/client/set_bucket_versioning.rs b/src/s3/client/put_bucket_versioning.rs similarity index 75% rename from src/s3/client/set_bucket_versioning.rs rename to src/s3/client/put_bucket_versioning.rs index 45b23a4..132a1ca 100644 --- a/src/s3/client/set_bucket_versioning.rs +++ b/src/s3/client/put_bucket_versioning.rs @@ -16,13 +16,13 @@ //! S3 APIs for bucket objects. use super::Client; -use crate::s3::builders::SetBucketVersioning; +use crate::s3::builders::PutBucketVersioning; impl Client { - /// Creates a [`SetBucketVersioning`] request builder. + /// Creates a [`PutBucketVersioning`] request builder. /// /// To execute the request, call [`SetBucketVersioning::send()`](crate::s3::types::S3Api::send), - /// which returns a [`Result`] containing a [`SetBucketVersioningResponse`](crate::s3::response::SetBucketVersioningResponse). + /// which returns a [`Result`] containing a [`SetBucketVersioningResponse`](crate::s3::response::PutBucketVersioningResponse). /// /// 🛈 This operation is not supported for express buckets. /// @@ -31,22 +31,21 @@ impl Client { /// ```no_run /// use minio::s3::Client; /// use minio::s3::builders::VersioningStatus; - /// use minio::s3::response::SetBucketVersioningResponse; + /// use minio::s3::response::PutBucketVersioningResponse; /// use minio::s3::types::{S3Api, ObjectLockConfig, RetentionMode}; /// - /// /// #[tokio::main] /// async fn main() { /// let client: Client = Default::default(); // configure your client here /// - /// let resp: SetBucketVersioningResponse = client - /// .set_bucket_versioning("bucket-name") + /// let resp: PutBucketVersioningResponse = client + /// .put_bucket_versioning("bucket-name") /// .versioning_status(VersioningStatus::Enabled) /// .send().await.unwrap(); /// println!("enabled versioning on bucket '{}'", resp.bucket); /// } /// ``` - pub fn set_bucket_versioning>(&self, bucket: S) -> SetBucketVersioning { - SetBucketVersioning::new(self.clone(), bucket.into()) + pub fn put_bucket_versioning>(&self, bucket: S) -> PutBucketVersioning { + PutBucketVersioning::new(self.clone(), bucket.into()) } } diff --git a/src/s3/client/put_object.rs b/src/s3/client/put_object.rs index bb3a9f2..2efaee7 100644 --- a/src/s3/client/put_object.rs +++ b/src/s3/client/put_object.rs @@ -40,7 +40,6 @@ impl Client { /// use minio::s3::types::S3Api; /// use minio::s3::segmented_bytes::SegmentedBytes; /// - /// /// #[tokio::main] /// async fn main() { /// let client: Client = Default::default(); // configure your client here diff --git a/src/s3/client/disable_object_legal_hold.rs b/src/s3/client/put_object_legal_hold.rs similarity index 64% rename from src/s3/client/disable_object_legal_hold.rs rename to src/s3/client/put_object_legal_hold.rs index 2d324a0..f7cc525 100644 --- a/src/s3/client/disable_object_legal_hold.rs +++ b/src/s3/client/put_object_legal_hold.rs @@ -16,13 +16,13 @@ //! S3 APIs for bucket objects. use super::Client; -use crate::s3::builders::DisableObjectLegalHold; +use crate::s3::builders::PutObjectLegalHold; impl Client { - /// Creates a [`DisableObjectLegalHold`] request builder. + /// Creates a [`PutObjectLegalHold`] request builder. /// /// To execute the request, call [`DisableObjectLegalHold::send()`](crate::s3::types::S3Api::send), - /// which returns a [`Result`] containing a [`DisableObjectLegalHoldResponse`](crate::s3::response::DisableObjectLegalHoldResponse). + /// which returns a [`Result`] containing a [`DisableObjectLegalHoldResponse`](crate::s3::response::PutObjectLegalHoldResponse). /// /// 🛈 This operation is not supported for express buckets. /// @@ -30,23 +30,25 @@ impl Client { /// /// ```no_run /// use minio::s3::Client; - /// use minio::s3::response::DisableObjectLegalHoldResponse; + /// use minio::s3::response::PutObjectLegalHoldResponse; /// use minio::s3::types::S3Api; /// - /// /// #[tokio::main] /// async fn main() { /// let client: Client = Default::default(); // configure your client here - /// let resp: DisableObjectLegalHoldResponse = - /// client.disable_object_legal_hold("bucket-name", "object-name").send().await.unwrap(); - /// println!("legal hold of bucket '{}' is deleted", resp.bucket); + /// let resp: PutObjectLegalHoldResponse = client + /// .put_object_legal_hold("bucket-name", "object-name", true) + /// .send().await.unwrap(); + /// println!("legal hold of bucket '{}' is enabled", resp.bucket); /// } /// ``` - pub fn disable_object_legal_hold, S2: Into>( + pub fn put_object_legal_hold, S2: Into>( &self, bucket: S1, object: S2, - ) -> DisableObjectLegalHold { - DisableObjectLegalHold::new(self.clone(), bucket.into(), object.into()) + legal_hold: bool, + ) -> PutObjectLegalHold { + PutObjectLegalHold::new(self.clone(), bucket.into(), object.into()) + .legal_hold(Some(legal_hold)) } } diff --git a/src/s3/client/set_object_lock_config.rs b/src/s3/client/put_object_lock_config.rs similarity index 72% rename from src/s3/client/set_object_lock_config.rs rename to src/s3/client/put_object_lock_config.rs index dc26ccc..ad01616 100644 --- a/src/s3/client/set_object_lock_config.rs +++ b/src/s3/client/put_object_lock_config.rs @@ -16,13 +16,13 @@ //! S3 APIs for bucket objects. use super::Client; -use crate::s3::builders::SetObjectLockConfig; +use crate::s3::builders::PutObjectLockConfig; impl Client { - /// Creates a [`SetObjectLockConfig`] request builder. + /// Creates a [`PutObjectLockConfig`] request builder. /// /// To execute the request, call [`SetObjectLockConfig::send()`](crate::s3::types::S3Api::send), - /// which returns a [`Result`] containing a [`SetObjectLockConfigResponse`](crate::s3::response::SetObjectLockConfigResponse). + /// which returns a [`Result`] containing a [`SetObjectLockConfigResponse`](crate::s3::response::PutObjectLockConfigResponse). /// /// 🛈 This operation is not supported for express buckets. /// @@ -30,28 +30,27 @@ impl Client { /// /// ```no_run /// use minio::s3::Client; - /// use minio::s3::response::{MakeBucketResponse, SetObjectLockConfigResponse}; + /// use minio::s3::response::{CreateBucketResponse, PutObjectLockConfigResponse}; /// use minio::s3::types::{S3Api, ObjectLockConfig, RetentionMode}; /// - /// /// #[tokio::main] /// async fn main() { /// let client: Client = Default::default(); // configure your client here /// let bucket_name = "bucket-name"; /// - /// let resp: MakeBucketResponse = - /// client.make_bucket(bucket_name).object_lock(true).send().await.unwrap(); + /// let resp: CreateBucketResponse = + /// client.create_bucket(bucket_name).object_lock(true).send().await.unwrap(); /// println!("created bucket '{}' with object locking enabled", resp.bucket); /// /// const DURATION_DAYS: i32 = 7; /// let config = ObjectLockConfig::new(RetentionMode::GOVERNANCE, Some(DURATION_DAYS), None).unwrap(); /// - /// let resp: SetObjectLockConfigResponse = - /// client.set_object_lock_config(bucket_name).config(config).send().await.unwrap(); + /// let resp: PutObjectLockConfigResponse = + /// client.put_object_lock_config(bucket_name).config(config).send().await.unwrap(); /// println!("configured object locking for bucket '{}'", resp.bucket); /// } /// ``` - pub fn set_object_lock_config>(&self, bucket: S) -> SetObjectLockConfig { - SetObjectLockConfig::new(self.clone(), bucket.into()) + pub fn put_object_lock_config>(&self, bucket: S) -> PutObjectLockConfig { + PutObjectLockConfig::new(self.clone(), bucket.into()) } } diff --git a/src/s3/client/set_object_retention.rs b/src/s3/client/put_object_retention.rs similarity index 77% rename from src/s3/client/set_object_retention.rs rename to src/s3/client/put_object_retention.rs index c67370c..726c48a 100644 --- a/src/s3/client/set_object_retention.rs +++ b/src/s3/client/put_object_retention.rs @@ -16,13 +16,13 @@ //! S3 APIs for bucket objects. use super::Client; -use crate::s3::builders::SetObjectRetention; +use crate::s3::builders::PutObjectRetention; impl Client { - /// Creates a [`SetObjectRetention`] request builder. + /// Creates a [`PutObjectRetention`] request builder. /// /// To execute the request, call [`SetObjectRetention::send()`](crate::s3::types::S3Api::send), - /// which returns a [`Result`] containing a [`SetObjectRetentionResponse`](crate::s3::response::SetObjectRetentionResponse). + /// which returns a [`Result`] containing a [`SetObjectRetentionResponse`](crate::s3::response::PutObjectRetentionResponse). /// /// 🛈 This operation is not supported for express buckets. /// @@ -30,29 +30,28 @@ impl Client { /// /// ```no_run /// use minio::s3::Client; - /// use minio::s3::response::SetObjectRetentionResponse; + /// use minio::s3::response::PutObjectRetentionResponse; /// use minio::s3::builders::ObjectToDelete; /// use minio::s3::types::{S3Api, RetentionMode}; /// use minio::s3::utils::utc_now; /// - /// /// #[tokio::main] /// async fn main() { /// let client: Client = Default::default(); // configure your client here /// let retain_until_date = utc_now() + chrono::Duration::days(1); - /// let resp: SetObjectRetentionResponse = client - /// .set_object_retention("bucket-name", "object-name") + /// let resp: PutObjectRetentionResponse = client + /// .put_object_retention("bucket-name", "object-name") /// .retention_mode(Some(RetentionMode::GOVERNANCE)) /// .retain_until_date(Some(retain_until_date)) /// .send().await.unwrap(); /// println!("set the object retention for object '{}'", resp.object); /// } /// ``` - pub fn set_object_retention, S2: Into>( + pub fn put_object_retention, S2: Into>( &self, bucket: S1, object: S2, - ) -> SetObjectRetention { - SetObjectRetention::new(self.clone(), bucket.into(), object.into()) + ) -> PutObjectRetention { + PutObjectRetention::new(self.clone(), bucket.into(), object.into()) } } diff --git a/src/s3/client/put_object_tagging.rs b/src/s3/client/put_object_tagging.rs new file mode 100644 index 0000000..b0429bf --- /dev/null +++ b/src/s3/client/put_object_tagging.rs @@ -0,0 +1,54 @@ +// 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. + +//! S3 APIs for bucket objects. + +use super::Client; +use crate::s3::builders::PutObjectTagging; + +impl Client { + /// Creates a [`PutObjectTagging`] request builder. + /// + /// To execute the request, call [`SetObjectTags::send()`](crate::s3::types::S3Api::send), + /// which returns a [`Result`] containing a [`SetObjectTagsResponse`](crate::s3::response::PutObjectTaggingResponse). + /// + /// 🛈 This operation is not supported for express buckets. + /// + /// # Example + /// + /// ```no_run + /// use std::collections::HashMap; + /// use minio::s3::Client; + /// use minio::s3::response::PutObjectTaggingResponse; + /// use minio::s3::types::S3Api; + /// + /// #[tokio::main] + /// async fn main() { + /// let client: Client = Default::default(); // configure your client here + /// let tags = HashMap::from([ + /// (String::from("Project"), String::from("Project One")), + /// (String::from("User"), String::from("jsmith")), + /// ]); + /// let resp: PutObjectTaggingResponse = client + /// .put_object_tagging("bucket-name", "object-name") + /// .tags(tags) + /// .send().await.unwrap(); + /// println!("set the object tags for object '{}'", resp.object); + /// } + /// ``` + pub fn put_object_tagging>(&self, bucket: S, object: S) -> PutObjectTagging { + PutObjectTagging::new(self.clone(), bucket.into(), object.into()) + } +} diff --git a/src/s3/client/set_bucket_encryption.rs b/src/s3/client/set_bucket_encryption.rs deleted file mode 100644 index 07a9241..0000000 --- a/src/s3/client/set_bucket_encryption.rs +++ /dev/null @@ -1,26 +0,0 @@ -// 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. - -//! S3 APIs for bucket objects. - -use super::Client; -use crate::s3::builders::SetBucketEncryption; - -impl Client { - /// Create a SetBucketEncryption request builder. - pub fn set_bucket_encryption>(&self, bucket: S) -> SetBucketEncryption { - SetBucketEncryption::new(self.clone(), bucket.into()) - } -} diff --git a/src/s3/client/set_object_tags.rs b/src/s3/client/set_object_tags.rs deleted file mode 100644 index fd1a736..0000000 --- a/src/s3/client/set_object_tags.rs +++ /dev/null @@ -1,33 +0,0 @@ -// 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. - -//! S3 APIs for bucket objects. - -use super::Client; -use crate::s3::builders::SetObjectTags; - -impl Client { - /// Create a SetObjectTags request builder. - /// - /// 🛈 This operation is not supported for express buckets. - /// - pub fn set_object_tags, S2: Into>( - &self, - bucket: S1, - object: S2, - ) -> SetObjectTags { - SetObjectTags::new(self.clone(), bucket.into(), object.into()) - } -} diff --git a/src/s3/client/stat_object.rs b/src/s3/client/stat_object.rs index 42d5386..cbc47b5 100644 --- a/src/s3/client/stat_object.rs +++ b/src/s3/client/stat_object.rs @@ -19,8 +19,7 @@ use super::Client; use crate::s3::builders::StatObject; impl Client { - /// Create a StatObject request builder. - /// Creates a [`StatObject`] request builder. + /// Creates a [`StatObject`] request builder. Given a bucket and object name, return some statistics. /// /// To execute the request, call [`StatObject::send()`](crate::s3::types::S3Api::send), /// which returns a [`Result`] containing a [`StatObjectResponse`](crate::s3::response::StatObjectResponse). @@ -32,7 +31,6 @@ impl Client { /// use minio::s3::response::StatObjectResponse; /// use minio::s3::types::S3Api; /// - /// /// #[tokio::main] /// async fn main() { /// let client: Client = Default::default(); // configure your client here diff --git a/src/s3/error.rs b/src/s3/error.rs index 2865f35..51c095b 100644 --- a/src/s3/error.rs +++ b/src/s3/error.rs @@ -185,44 +185,41 @@ impl std::error::Error for Error {} impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - Error::TimeParseError(e) => write!(f, "{}", e), - Error::InvalidUrl(e) => write!(f, "{}", e), - Error::IOError(e) => write!(f, "{}", e), - Error::XmlParseError(e) => write!(f, "{}", e), - Error::HttpError(e) => write!(f, "{}", e), - Error::StrError(e) => write!(f, "{}", e), - Error::IntError(e) => write!(f, "{}", e), - Error::BoolError(e) => write!(f, "{}", e), - Error::Utf8Error(e) => write!(f, "{}", e), - Error::JsonError(e) => write!(f, "{}", e), - Error::XmlError(m) => write!(f, "{}", m), - Error::InvalidBucketName(m) => write!(f, "{}", m), - Error::InvalidObjectName(m) => write!(f, "{}", m), - Error::InvalidUploadId(m) => write!(f, "{}", m), - Error::InvalidPartNumber(m) => write!(f, "{}", m), - Error::InvalidUserMetadata(m) => write!(f, "{}", m), - Error::EmptyParts(m) => write!(f, "{}", m), - Error::InvalidRetentionMode(m) => write!(f, "invalid retention mode {}", m), - Error::InvalidRetentionConfig(m) => write!(f, "invalid retention configuration; {}", m), + Error::TimeParseError(e) => write!(f, "{e}"), + Error::InvalidUrl(e) => write!(f, "{e}"), + Error::IOError(e) => write!(f, "{e}"), + Error::XmlParseError(e) => write!(f, "{e}"), + Error::HttpError(e) => write!(f, "{e}"), + Error::StrError(e) => write!(f, "{e}"), + Error::IntError(e) => write!(f, "{e}"), + Error::BoolError(e) => write!(f, "{e}"), + Error::Utf8Error(e) => write!(f, "{e}"), + Error::JsonError(e) => write!(f, "{e}"), + Error::XmlError(m) => write!(f, "{m}"), + Error::InvalidBucketName(m) => write!(f, "{m}"), + Error::InvalidObjectName(m) => write!(f, "{m}"), + Error::InvalidUploadId(m) => write!(f, "{m}"), + Error::InvalidPartNumber(m) => write!(f, "{m}"), + Error::InvalidUserMetadata(m) => write!(f, "{m}"), + Error::EmptyParts(m) => write!(f, "{m}"), + Error::InvalidRetentionMode(m) => write!(f, "invalid retention mode {m}"), + Error::InvalidRetentionConfig(m) => write!(f, "invalid retention configuration; {m}"), Error::InvalidMinPartSize(s) => { - write!(f, "part size {} is not supported; minimum allowed 5MiB", s) + write!(f, "part size {s} is not supported; minimum allowed 5MiB") } Error::InvalidMaxPartSize(s) => { - write!(f, "part size {} is not supported; maximum allowed 5GiB", s) + write!(f, "part size {s} is not supported; maximum allowed 5GiB") + } + Error::InvalidObjectSize(s) => { + write!(f, "object size {s} is not supported; maximum allowed 5TiB",) } - Error::InvalidObjectSize(s) => write!( - f, - "object size {} is not supported; maximum allowed 5TiB", - s - ), Error::MissingPartSize => write!( f, "valid part size must be provided when object size is unknown" ), Error::InvalidPartCount(os, ps, pc) => write!( f, - "object size {} and part size {} make more than {} parts for upload", - os, ps, pc + "object size {os} and part size {ps} make more than {pc} parts for upload" ), Error::TooManyParts => write!(f, "too many parts for upload"), Error::SseTlsRequired(m) => write!( @@ -230,16 +227,15 @@ impl fmt::Display for Error { "{}SSE operation must be performed over a secure connection", m.as_ref().map_or(String::new(), |v| v.clone()) ), - Error::TooMuchData(s) => write!(f, "too much data in the stream - exceeds {} bytes", s), + Error::TooMuchData(s) => write!(f, "too much data in the stream - exceeds {s} bytes"), Error::InsufficientData(expected, got) => write!( f, - "not enough data in the stream; expected: {}, got: {} bytes", - expected, got + "not enough data in the stream; expected: {expected}, got: {got} bytes", ), - Error::InvalidBaseUrl(m) => write!(f, "{}", m), - Error::UrlBuildError(m) => write!(f, "{}", m), - Error::InvalidLegalHold(s) => write!(f, "invalid legal hold {}", s), - Error::RegionMismatch(br, r) => write!(f, "region must be {}, but passed {}", br, r), + Error::InvalidBaseUrl(m) => write!(f, "{m}"), + Error::UrlBuildError(m) => write!(f, "{m}"), + Error::InvalidLegalHold(s) => write!(f, "invalid legal hold {s}"), + Error::RegionMismatch(br, r) => write!(f, "region must be {br}, but passed {r}"), Error::S3Error(er) => write!( f, "s3 operation failed; code: {:?}, message: {}, resource: {}, request_id: {}, host_id: {}, bucket_name: {}, object_name: {}", @@ -253,19 +249,18 @@ impl fmt::Display for Error { ), Error::InvalidResponse(sc, ct) => write!( f, - "invalid response received; status code: {}; content-type: {}", - sc, ct + "invalid response received; status code: {sc}; content-type: {ct}" ), - Error::ServerError(sc) => write!(f, "server failed with HTTP status code {}", sc), - Error::InvalidSelectExpression(m) => write!(f, "{}", m), - Error::InvalidHeaderValueType(v) => write!(f, "invalid header value type {}", v), + Error::ServerError(sc) => write!(f, "server failed with HTTP status code {sc}"), + Error::InvalidSelectExpression(m) => write!(f, "{m}"), + Error::InvalidHeaderValueType(v) => write!(f, "invalid header value type {v}"), Error::CrcMismatch(t, e, g) => { - write!(f, "{} CRC mismatch; expected: {}, got: {}", t, e, g) + write!(f, "{t} CRC mismatch; expected: {e}, got: {g}") } - Error::UnknownEventType(et) => write!(f, "unknown event type {}", et), - Error::SelectError(ec, em) => write!(f, "error code: {}, error message: {}", ec, em), - Error::UnsupportedApi(a) => write!(f, "{} API is not supported in Amazon AWS S3", a), - Error::InvalidComposeSource(m) => write!(f, "{}", m), + Error::UnknownEventType(et) => write!(f, "unknown event type {et}"), + Error::SelectError(ec, em) => write!(f, "error code: {ec}, error message: {em}"), + Error::UnsupportedApi(a) => write!(f, "{a} API is not supported in Amazon AWS S3"), + Error::InvalidComposeSource(m) => write!(f, "{m}"), Error::InvalidComposeSourceOffset(b, o, v, of, os) => write!( f, "source {}/{}{}: offset {} is beyond object size {}", @@ -296,8 +291,8 @@ impl fmt::Display for Error { cs, os ), - Error::InvalidDirective(m) => write!(f, "{}", m), - Error::InvalidCopyDirective(m) => write!(f, "{}", m), + Error::InvalidDirective(m) => write!(f, "{m}"), + Error::InvalidCopyDirective(m) => write!(f, "{m}"), Error::InvalidComposeSourcePartSize(b, o, v, s, es) => write!( f, "source {}/{}{}: size {} must be greater than {}", @@ -321,8 +316,7 @@ impl fmt::Display for Error { ), Error::InvalidMultipartCount(c) => write!( f, - "Compose sources create more than allowed multipart count {}", - c + "Compose sources create more than allowed multipart count {c}", ), Error::MissingLifecycleAction => write!( f, @@ -333,19 +327,17 @@ impl fmt::Display for Error { "ExpiredObjectDeleteMarker must not be provided along with Date and Days" ), Error::InvalidDateAndDays(m) => { - write!(f, "Only one of date or days of {} must be set", m) + write!(f, "Only one of date or days of {m} must be set") } Error::InvalidLifecycleRuleId => write!(f, "id must be exceed 255 characters"), Error::InvalidFilter => write!(f, "only one of And, Prefix or Tag must be provided"), - Error::InvalidVersioningStatus(m) => write!(f, "{}", m), - Error::PostPolicyError(m) => write!(f, "{}", m), - Error::InvalidObjectLockConfig(m) => write!(f, "{}", m), + Error::InvalidVersioningStatus(m) => write!(f, "{m}"), + Error::PostPolicyError(m) => write!(f, "{m}"), + Error::InvalidObjectLockConfig(m) => write!(f, "{m}"), Error::NoClientProvided => write!(f, "no client provided"), - Error::TagDecodingError(input, error_message) => write!( - f, - "tag decoding failed: {} on input '{}'", - error_message, input - ), + Error::TagDecodingError(input, error_message) => { + write!(f, "tag decoding failed: {error_message} on input '{input}'") + } Error::ContentLengthUnknown => write!(f, "content length is unknown"), } } diff --git a/src/s3/http.rs b/src/s3/http.rs index f2008da..5ccda4e 100644 --- a/src/s3/http.rs +++ b/src/s3/http.rs @@ -129,18 +129,18 @@ pub fn match_aws_s3_endpoint(value: &str) -> bool { } fn get_aws_info( - host: &String, + host: &str, https: bool, region: &mut String, aws_s3_prefix: &mut String, aws_domain_suffix: &mut String, dualstack: &mut bool, ) -> Result<(), Error> { - if !match_hostname(host.as_str()) { + if !match_hostname(host) { return Ok(()); } - if AWS_ELB_ENDPOINT_REGEX.is_match(host.as_str()) { + if AWS_ELB_ENDPOINT_REGEX.is_match(host) { let token = host .get(..host.rfind(".elb.amazonaws.com").unwrap() - 1) .unwrap(); @@ -151,17 +151,17 @@ fn get_aws_info( return Ok(()); } - if !match_aws_endpoint(host.as_str()) { + if !match_aws_endpoint(host) { return Ok(()); } - if !match_aws_s3_endpoint(host.as_str()) { + if !match_aws_s3_endpoint(host) { return Err(Error::UrlBuildError( String::from("invalid Amazon AWS host ") + host, )); } - let matcher = AWS_S3_PREFIX_REGEX.find(host.as_str()).unwrap(); + let matcher = AWS_S3_PREFIX_REGEX.find(host).unwrap(); let s3_prefix = host.get(..matcher.end()).unwrap(); if s3_prefix.contains("s3-accesspoint") && !https { @@ -301,7 +301,7 @@ impl FromStr for BaseUrl { let mut aws_domain_suffix = String::new(); let mut dualstack: bool = false; get_aws_info( - &host.to_string(), + host, https, &mut region, &mut aws_s3_prefix, diff --git a/src/s3/object_content.rs b/src/s3/object_content.rs index 2e7d9f1..5e4ac4a 100644 --- a/src/s3/object_content.rs +++ b/src/s3/object_content.rs @@ -31,9 +31,10 @@ type IoResult = Result; // region: Size -#[derive(Debug, Clone, PartialEq, Eq, Copy)] +#[derive(Debug, Clone, PartialEq, Eq, Copy, Default)] pub enum Size { Known(u64), + #[default] Unknown, } @@ -196,10 +197,11 @@ impl ObjectContent { if file_path.is_dir() { return Err(std::io::Error::other("path is a directory")); } - let parent_dir = file_path.parent().ok_or(std::io::Error::other(format!( - "path {:?} does not have a parent directory", - file_path - )))?; + let parent_dir = file_path.parent().ok_or_else(|| { + std::io::Error::other(format!( + "path {file_path:?} does not have a parent directory" + )) + })?; if !parent_dir.is_dir() { fs::create_dir_all(parent_dir).await?; } @@ -240,6 +242,12 @@ pub(crate) struct ContentStream { size: Size, } +impl Default for ContentStream { + fn default() -> Self { + ContentStream::empty() + } +} + impl ContentStream { pub fn new( r: impl Stream> + Send + 'static, diff --git a/src/s3/response.rs b/src/s3/response.rs index ad221bd..fd9b462 100644 --- a/src/s3/response.rs +++ b/src/s3/response.rs @@ -18,100 +18,98 @@ mod append_object; mod bucket_exists; mod copy_object; +mod create_bucket; +mod delete_bucket; mod delete_bucket_encryption; mod delete_bucket_lifecycle; mod delete_bucket_notification; mod delete_bucket_policy; mod delete_bucket_replication; -mod delete_bucket_tags; +mod delete_bucket_tagging; mod delete_object_lock_config; -mod delete_object_tags; -mod disable_object_legal_hold; -mod enable_object_legal_hold; +mod delete_object_tagging; mod get_bucket_encryption; mod get_bucket_lifecycle; mod get_bucket_notification; mod get_bucket_policy; mod get_bucket_replication; -mod get_bucket_tags; +mod get_bucket_tagging; mod get_bucket_versioning; mod get_object; +mod get_object_legal_hold; mod get_object_lock_config; +mod get_object_prompt; mod get_object_retention; -mod get_object_tags; +mod get_object_tagging; mod get_presigned_object_url; mod get_region; -mod is_object_legal_hold_enabled; +mod list_bucket_notification; mod list_buckets; pub(crate) mod list_objects; -mod listen_bucket_notification; -mod make_bucket; -mod object_prompt; +mod put_bucket_encryption; +mod put_bucket_lifecycle; +mod put_bucket_notification; +mod put_bucket_policy; +mod put_bucket_replication; +mod put_bucket_tagging; +mod put_bucket_versioning; mod put_object; -mod remove_bucket; +mod put_object_legal_hold; +mod put_object_lock_config; +mod put_object_retention; +mod put_object_tagging; mod remove_objects; mod select_object_content; -mod set_bucket_encryption; -mod set_bucket_lifecycle; -mod set_bucket_notification; -mod set_bucket_policy; -mod set_bucket_replication; -mod set_bucket_tags; -mod set_bucket_versioning; -mod set_object_lock_config; -mod set_object_retention; -mod set_object_tags; mod stat_object; pub use append_object::AppendObjectResponse; pub use bucket_exists::BucketExistsResponse; pub use copy_object::*; +pub use create_bucket::CreateBucketResponse; +pub use delete_bucket::DeleteBucketResponse; pub use delete_bucket_encryption::DeleteBucketEncryptionResponse; pub use delete_bucket_lifecycle::DeleteBucketLifecycleResponse; pub use delete_bucket_notification::DeleteBucketNotificationResponse; pub use delete_bucket_policy::DeleteBucketPolicyResponse; pub use delete_bucket_replication::DeleteBucketReplicationResponse; -pub use delete_bucket_tags::DeleteBucketTagsResponse; +pub use delete_bucket_tagging::DeleteBucketTaggingResponse; pub use delete_object_lock_config::DeleteObjectLockConfigResponse; -pub use delete_object_tags::DeleteObjectTagsResponse; -pub use disable_object_legal_hold::DisableObjectLegalHoldResponse; -pub use enable_object_legal_hold::EnableObjectLegalHoldResponse; +pub use delete_object_tagging::DeleteObjectTaggingResponse; pub use get_bucket_encryption::GetBucketEncryptionResponse; pub use get_bucket_lifecycle::GetBucketLifecycleResponse; pub use get_bucket_notification::GetBucketNotificationResponse; pub use get_bucket_policy::GetBucketPolicyResponse; pub use get_bucket_replication::GetBucketReplicationResponse; -pub use get_bucket_tags::GetBucketTagsResponse; +pub use get_bucket_tagging::GetBucketTaggingResponse; pub use get_bucket_versioning::GetBucketVersioningResponse; pub use get_object::GetObjectResponse; +pub use get_object_legal_hold::GetObjectLegalHoldResponse; pub use get_object_lock_config::GetObjectLockConfigResponse; +pub use get_object_prompt::GetObjectPromptResponse; pub use get_object_retention::GetObjectRetentionResponse; -pub use get_object_tags::GetObjectTagsResponse; +pub use get_object_tagging::GetObjectTaggingResponse; pub use get_presigned_object_url::GetPresignedObjectUrlResponse; pub use get_region::GetRegionResponse; -pub use is_object_legal_hold_enabled::IsObjectLegalHoldEnabledResponse; +pub use list_bucket_notification::ListBucketNotificationResponse; pub use list_buckets::ListBucketsResponse; pub use list_objects::ListObjectsResponse; -pub use listen_bucket_notification::ListenBucketNotificationResponse; -pub use make_bucket::MakeBucketResponse; -pub use object_prompt::ObjectPromptResponse; +pub use put_bucket_encryption::PutBucketEncryptionResponse; +pub use put_bucket_lifecycle::PutBucketLifecycleResponse; +pub use put_bucket_notification::PutBucketNotificationResponse; +pub use put_bucket_policy::PutBucketPolicyResponse; +pub use put_bucket_replication::PutBucketReplicationResponse; +pub use put_bucket_tagging::PutBucketTaggingResponse; +pub use put_bucket_versioning::PutBucketVersioningResponse; pub use put_object::{ AbortMultipartUploadResponse, CompleteMultipartUploadResponse, CreateMultipartUploadResponse, PutObjectContentResponse, PutObjectResponse, UploadPartResponse, }; -pub use remove_bucket::RemoveBucketResponse; +pub use put_object_legal_hold::PutObjectLegalHoldResponse; +pub use put_object_lock_config::PutObjectLockConfigResponse; +pub use put_object_retention::PutObjectRetentionResponse; +pub use put_object_tagging::PutObjectTaggingResponse; pub use remove_objects::{ DeleteError, DeleteResult, DeletedObject, RemoveObjectResponse, RemoveObjectsResponse, }; pub use select_object_content::SelectObjectContentResponse; -pub use set_bucket_encryption::SetBucketEncryptionResponse; -pub use set_bucket_lifecycle::SetBucketLifecycleResponse; -pub use set_bucket_notification::SetBucketNotificationResponse; -pub use set_bucket_policy::SetBucketPolicyResponse; -pub use set_bucket_replication::SetBucketReplicationResponse; -pub use set_bucket_tags::SetBucketTagsResponse; -pub use set_bucket_versioning::SetBucketVersioningResponse; -pub use set_object_lock_config::SetObjectLockConfigResponse; -pub use set_object_retention::SetObjectRetentionResponse; -pub use set_object_tags::SetObjectTagsResponse; pub use stat_object::StatObjectResponse; diff --git a/src/s3/response/append_object.rs b/src/s3/response/append_object.rs index d84709a..b00e577 100644 --- a/src/s3/response/append_object.rs +++ b/src/s3/response/append_object.rs @@ -20,16 +20,38 @@ use async_trait::async_trait; use http::HeaderMap; use std::mem; +/// Represents the response of the `append_object` API call. +/// This struct contains metadata and information about the object being appended. +/// +/// # Fields +/// +/// * `headers` - HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. +/// * `region` - The AWS region where the bucket resides. +/// * `bucket` - Name of the bucket containing the object. +/// * `object` - Key (path) identifying the object within the bucket. +/// * `etag` - Entity tag representing a specific version of the object. +/// * `version_id` - Version ID of the object, if versioning is enabled. Value of the `x-amz-version-id` header. +/// * `object_size` - Value of the `x-amz-object-size` header. #[derive(Debug, Clone)] pub struct AppendObjectResponse { - /// set of HTTP headers returned by the server. + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, - pub bucket: String, - pub object: String, + + /// The AWS region where the bucket resides. pub region: String, + + /// Name of the bucket containing the object. + pub bucket: String, + + /// Key (path) identifying the object within the bucket. + pub object: String, + + /// Entity tag representing a specific version of the object. pub etag: String, - /// Value of the `x-amz-version-id` header. + + /// Version ID of the object, if versioning is enabled. Value of the `x-amz-version-id` header. pub version_id: Option, + /// Value of the `x-amz-object-size` header. pub object_size: u64, } diff --git a/src/s3/response/bucket_exists.rs b/src/s3/response/bucket_exists.rs index ab60fc0..ff71cbe 100644 --- a/src/s3/response/bucket_exists.rs +++ b/src/s3/response/bucket_exists.rs @@ -20,15 +20,27 @@ use async_trait::async_trait; use http::HeaderMap; use std::mem; -/// Response of -/// [bucket_exists()](crate::s3::client::Client::bucket_exists) -/// API +/// Represents the response of the [bucket_exists()](crate::s3::client::Client::bucket_exists) API call. +/// This struct contains metadata and information about the existence of a bucket. +/// +/// # Fields +/// +/// * `headers` - HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. +/// * `region` - The AWS region where the bucket resides. If the bucket does not exist, this will be an empty string. +/// * `bucket` - The name of the bucket being checked. +/// * `exists` - A boolean indicating whether the bucket exists or not. #[derive(Clone, Debug)] pub struct BucketExistsResponse { - /// Set of HTTP headers returned by the server. + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, + + /// The AWS region where the bucket resides. pub region: String, + + /// The name of the bucket being checked. pub bucket: String, + + /// Whether the bucket exists or not. pub exists: bool, } diff --git a/src/s3/response/copy_object.rs b/src/s3/response/copy_object.rs index 4bf6572..ab3e66c 100644 --- a/src/s3/response/copy_object.rs +++ b/src/s3/response/copy_object.rs @@ -22,15 +22,35 @@ use http::HeaderMap; use std::mem; use xmltree::Element; +/// Represents the response of the `upload_part_copy` API call. +/// This struct contains metadata and information about the part being copied during a multipart upload. +/// +/// # Fields +/// +/// * `headers` - HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. +/// * `region` - The AWS region where the bucket resides. +/// * `bucket` - Name of the bucket containing the object. +/// * `object` - Key (path) identifying the object within the bucket. +/// * `etag` - Entity tag representing a specific version of the object. +/// * `version_id` - Version ID of the object, if versioning is enabled. Value of the `x-amz-version-id` header. #[derive(Clone, Debug)] pub struct UploadPartCopyResponse { - /// Set of HTTP headers returned by the server. + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, + + /// The AWS region where the bucket resides. pub region: String, + + /// Name of the bucket containing the object. pub bucket: String, + /// Key (path) identifying the object within the bucket. pub object: String, + + /// Entity tag representing a specific version of the object. pub etag: String, + + /// Version ID of the object, if versioning is enabled. Value of the `x-amz-version-id` header. pub version_id: Option, } @@ -67,7 +87,7 @@ impl FromS3Response for UploadPartCopyResponse { #[derive(Clone, Debug)] pub struct CopyObjectInternalResponse { - /// Set of HTTP headers returned by the server. + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, pub region: String, pub bucket: String, @@ -114,29 +134,66 @@ impl FromS3Response for CopyObjectInternalResponse { } } -/// Response of -/// [copy_object()](crate::s3::client::Client::copy_object_old) -/// API +/// Represents the response of the `copy_object` API call. +/// This struct contains metadata and information about the object being copied. +/// +/// # Fields +/// +/// * `headers` - HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. +/// * `region` - The AWS region where the bucket resides. +/// * `bucket` - Name of the bucket containing the object. +/// * `object` - Key (path) identifying the object within the bucket. +/// * `etag` - Entity tag representing a specific version of the object. +/// * `version_id` - Version ID of the object, if versioning is enabled. Value of the `x-amz-version-id` header. #[derive(Clone, Debug)] pub struct CopyObjectResponse { - /// Set of HTTP headers returned by the server. + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, + + /// The AWS region where the bucket resides. pub region: String, + + /// Name of the bucket containing the object. pub bucket: String, + /// Key (path) identifying the object within the bucket. pub object: String, + + /// Entity tag representing a specific version of the object. pub etag: String, + + /// Version ID of the object, if versioning is enabled. Value of the `x-amz-version-id` header. pub version_id: Option, } -/// Response of [compose_object()](crate::s3::client::Client::compose_object) API +/// Represents the response of the `[compose_object()](crate::s3::client::Client::compose_object) API call. +/// This struct contains metadata and information about the composed object. +/// +/// # Fields +/// +/// * `headers` - HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. +/// * `bucket` - Name of the bucket containing the composed object. +/// * `object` - Key (path) identifying the composed object within the bucket. +/// * `region` - The AWS region where the bucket resides. +/// * `etag` - Entity tag representing a specific version of the composed object. +/// * `version_id` - Version ID of the composed object, if versioning is enabled. #[derive(Debug, Clone)] pub struct ComposeObjectResponse { + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, + + /// Name of the bucket containing the composed object. pub bucket: String, + + /// Key (path) identifying the composed object within the bucket. pub object: String, + /// The AWS region where the bucket resides. pub region: String, + + /// Entity tag representing a specific version of the composed object. pub etag: String, + + /// Version ID of the composed object, if versioning is enabled. pub version_id: Option, } diff --git a/src/s3/response/make_bucket.rs b/src/s3/response/create_bucket.rs similarity index 80% rename from src/s3/response/make_bucket.rs rename to src/s3/response/create_bucket.rs index e335c78..9b5c33a 100644 --- a/src/s3/response/make_bucket.rs +++ b/src/s3/response/create_bucket.rs @@ -21,18 +21,22 @@ use http::HeaderMap; use std::mem; /// Response of -/// [make_bucket()](crate::s3::client::Client::make_bucket) +/// [create_bucket()](crate::s3::client::Client::create_bucket) /// API #[derive(Clone, Debug)] -pub struct MakeBucketResponse { - /// Set of HTTP headers returned by the server. +pub struct CreateBucketResponse { + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, + + /// The AWS region where the bucket resides. pub region: String, + + /// Name of the bucket containing the object. pub bucket: String, } #[async_trait] -impl FromS3Response for MakeBucketResponse { +impl FromS3Response for CreateBucketResponse { async fn from_s3response( req: S3Request, resp: Result, diff --git a/src/s3/response/remove_bucket.rs b/src/s3/response/delete_bucket.rs similarity index 80% rename from src/s3/response/remove_bucket.rs rename to src/s3/response/delete_bucket.rs index e6a9588..24d16de 100644 --- a/src/s3/response/remove_bucket.rs +++ b/src/s3/response/delete_bucket.rs @@ -21,18 +21,22 @@ use http::HeaderMap; use std::mem; /// Response of -/// [remove_bucket()](crate::s3::client::Client::remove_bucket) +/// [delete_bucket()](crate::s3::client::Client::delete_bucket) /// API #[derive(Clone, Debug)] -pub struct RemoveBucketResponse { - /// Set of HTTP headers returned by the server. +pub struct DeleteBucketResponse { + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, + + /// The AWS region where the bucket resides. pub region: String, + + /// Name of the bucket containing the object. pub bucket: String, } #[async_trait] -impl FromS3Response for RemoveBucketResponse { +impl FromS3Response for DeleteBucketResponse { async fn from_s3response( req: S3Request, resp: Result, diff --git a/src/s3/response/delete_bucket_encryption.rs b/src/s3/response/delete_bucket_encryption.rs index 140fcab..ce5acad 100644 --- a/src/s3/response/delete_bucket_encryption.rs +++ b/src/s3/response/delete_bucket_encryption.rs @@ -20,14 +20,23 @@ use async_trait::async_trait; use http::HeaderMap; use std::mem; -/// Response of -/// [delete_bucket_encryption()](crate::s3::client::Client::delete_bucket_encryption) -/// API +/// Represents the response of the [delete_bucket_encryption()](crate::s3::client::Client::delete_bucket_encryption) API call. +/// This struct contains metadata and information about the bucket whose encryption configuration was removed. +/// +/// # Fields +/// +/// * `headers` - HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. +/// * `region` - The AWS region where the bucket resides. +/// * `bucket` - Name of the bucket from which the encryption configuration was removed. #[derive(Clone, Debug)] pub struct DeleteBucketEncryptionResponse { - /// Set of HTTP headers returned by the server. + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, + + /// The AWS region where the bucket resides. pub region: String, + + /// Name of the bucket from which the Encryption configuration was removed. pub bucket: String, } diff --git a/src/s3/response/delete_bucket_lifecycle.rs b/src/s3/response/delete_bucket_lifecycle.rs index 27dcda1..dbc691e 100644 --- a/src/s3/response/delete_bucket_lifecycle.rs +++ b/src/s3/response/delete_bucket_lifecycle.rs @@ -20,14 +20,23 @@ use async_trait::async_trait; use http::HeaderMap; use std::mem; -/// Response of -/// [delete_bucket_lifecycle()](crate::s3::client::Client::delete_bucket_lifecycle) -/// API +/// Represents the response of the [delete_bucket_lifecycle()](crate::s3::client::Client::delete_bucket_lifecycle) API call. +/// This struct contains metadata and information about the bucket whose lifecycle configuration was removed. +/// +/// # Fields +/// +/// * `headers` - HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. +/// * `region` - The AWS region where the bucket resides. +/// * `bucket` - Name of the bucket from which the Bucket Lifecycle configuration was removed. #[derive(Clone, Debug)] pub struct DeleteBucketLifecycleResponse { - /// Set of HTTP headers returned by the server. + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, + + /// The AWS region where the bucket resides. pub region: String, + + /// Name of the bucket from which the Bucket Lifecycle configuration was removed. pub bucket: String, } diff --git a/src/s3/response/delete_bucket_notification.rs b/src/s3/response/delete_bucket_notification.rs index f4d3472..e7b1e4c 100644 --- a/src/s3/response/delete_bucket_notification.rs +++ b/src/s3/response/delete_bucket_notification.rs @@ -20,14 +20,23 @@ use async_trait::async_trait; use http::HeaderMap; use std::mem; -/// Response of -/// [delete_bucket_notification()](crate::s3::client::Client::delete_bucket_notification) -/// API +/// Represents the response of the [delete_bucket_notification()](crate::s3::client::Client::delete_bucket_notification) API call. +/// This struct contains metadata and information about the bucket whose notifications were removed. +/// +/// # Fields +/// +/// * `headers` - HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. +/// * `region` - The AWS region where the bucket resides. +/// * `bucket` - Name of the bucket from which the Bucket Notifications were removed. #[derive(Clone, Debug)] pub struct DeleteBucketNotificationResponse { - /// Set of HTTP headers returned by the server. + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, + + /// The AWS region where the bucket resides. pub region: String, + + /// Name of the bucket from which the Bucket Notifications were removed. pub bucket: String, } diff --git a/src/s3/response/delete_bucket_policy.rs b/src/s3/response/delete_bucket_policy.rs index ce2bb12..9448f38 100644 --- a/src/s3/response/delete_bucket_policy.rs +++ b/src/s3/response/delete_bucket_policy.rs @@ -20,14 +20,23 @@ use async_trait::async_trait; use http::HeaderMap; use std::mem; -/// Response of -/// [delete_bucket_policy()](crate::s3::client::Client::delete_bucket_policy) -/// API +/// Represents the response of the [delete_bucket_policy()](crate::s3::client::Client::delete_bucket_policy) API call. +/// This struct contains metadata and information about the bucket whose policy was removed. +/// +/// # Fields +/// +/// * `headers` - HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. +/// * `region` - The AWS region where the bucket resides. +/// * `bucket` - Name of the bucket from which the Bucket Policy was removed. #[derive(Clone, Debug)] pub struct DeleteBucketPolicyResponse { - /// Set of HTTP headers returned by the server. + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, + + /// The AWS region where the bucket resides. pub region: String, + + /// Name of the bucket from which the Bucket Policy was removed. pub bucket: String, } diff --git a/src/s3/response/delete_bucket_replication.rs b/src/s3/response/delete_bucket_replication.rs index daadde1..5bb05cd 100644 --- a/src/s3/response/delete_bucket_replication.rs +++ b/src/s3/response/delete_bucket_replication.rs @@ -20,14 +20,23 @@ use async_trait::async_trait; use http::HeaderMap; use std::mem; -/// Response of -/// [delete_bucket_replication()](crate::s3::client::Client::delete_bucket_replication) -/// API +/// Represents the response of the `[delete_bucket_replication()](crate::s3::client::Client::delete_bucket_replication) API call. +/// This struct contains metadata and information about the bucket whose replication configuration was removed. +/// +/// # Fields +/// +/// * `headers` - HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. +/// * `region` - The AWS region where the bucket resides. +/// * `bucket` - Name of the bucket from which the Replication configuration was removed. #[derive(Clone, Debug)] pub struct DeleteBucketReplicationResponse { - /// Set of HTTP headers returned by the server. + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, + + /// The AWS region where the bucket resides. pub region: String, + + /// Name of the bucket from which the Replication configuration was removed. pub bucket: String, } diff --git a/src/s3/response/set_object_lock_config.rs b/src/s3/response/delete_bucket_tagging.rs similarity index 62% rename from src/s3/response/set_object_lock_config.rs rename to src/s3/response/delete_bucket_tagging.rs index d8a16c9..db68055 100644 --- a/src/s3/response/set_object_lock_config.rs +++ b/src/s3/response/delete_bucket_tagging.rs @@ -20,19 +20,28 @@ use async_trait::async_trait; use http::HeaderMap; use std::mem; -/// Response of -/// [set_object_lock_config_response()](crate::s3::client::Client::set_object_lock_config_response) -/// API +/// Represents the response of the [delete_bucket_tagging()](crate::s3::client::Client::delete_bucket_tagging) API call. +/// This struct contains metadata and information about the bucket whose tags were removed. +/// +/// # Fields +/// +/// * `headers` - HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. +/// * `region` - The AWS region where the bucket resides. +/// * `bucket` - Name of the bucket from which the tags were removed. #[derive(Clone, Debug)] -pub struct SetObjectLockConfigResponse { - /// Set of HTTP headers returned by the server. +pub struct DeleteBucketTaggingResponse { + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, + + /// The AWS region where the bucket resides. pub region: String, + + /// Name of the bucket from which the tags were removed. pub bucket: String, } #[async_trait] -impl FromS3Response for SetObjectLockConfigResponse { +impl FromS3Response for DeleteBucketTaggingResponse { async fn from_s3response( req: S3Request, resp: Result, diff --git a/src/s3/response/delete_object_lock_config.rs b/src/s3/response/delete_object_lock_config.rs index 4cab89e..c83724c 100644 --- a/src/s3/response/delete_object_lock_config.rs +++ b/src/s3/response/delete_object_lock_config.rs @@ -20,14 +20,22 @@ use async_trait::async_trait; use http::HeaderMap; use std::mem; -/// Response of -/// [delete_object_lock_config_response()](crate::s3::client::Client::delete_object_lock_config_response) -/// API +/// Response from the [`delete_object_lock_config`](crate::s3::client::Client::delete_object_lock_config) API call, +/// indicating that the Object Lock configuration has been successfully removed from the specified S3 bucket. +/// +/// Removing the Object Lock configuration disables the default retention settings for new objects added to the bucket. +/// Existing object versions with retention settings or legal holds remain unaffected. +/// +/// For more information, refer to the [AWS S3 DeleteObjectLockConfiguration API documentation](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObjectLockConfiguration.html). #[derive(Clone, Debug)] pub struct DeleteObjectLockConfigResponse { - /// Set of HTTP headers returned by the server. + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, + + /// The AWS region where the bucket resides. pub region: String, + + /// Name of the bucket from which the Object Lock configuration was removed. pub bucket: String, } diff --git a/src/s3/response/delete_object_tags.rs b/src/s3/response/delete_object_tagging.rs similarity index 57% rename from src/s3/response/delete_object_tags.rs rename to src/s3/response/delete_object_tagging.rs index e825fda..67472d6 100644 --- a/src/s3/response/delete_object_tags.rs +++ b/src/s3/response/delete_object_tagging.rs @@ -21,21 +21,35 @@ use async_trait::async_trait; use http::HeaderMap; use std::mem; -/// Response of -/// [delete_object_tags()](crate::s3::client::Client::delete_object_tags) -/// API +/// Response from the [`delete_object_tagging`](crate::s3::client::Client::delete_object_tagging) API call, +/// indicating that all tags have been successfully removed from a specific object (or object version) in an S3 bucket. +/// +/// This operation deletes the entire tag set associated with the specified object. If the bucket is versioning-enabled, +/// you can specify a version ID to remove tags from a specific version of the object. +/// +/// For more information, refer to the [AWS S3 DeleteObjectTagging API documentation](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObjectTagging.html). #[derive(Clone, Debug)] -pub struct DeleteObjectTagsResponse { - /// Set of HTTP headers returned by the server. +pub struct DeleteObjectTaggingResponse { + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, + + /// The AWS region where the bucket resides. pub region: String, + + /// Name of the bucket containing the object. pub bucket: String, + + /// Key (name) identifying the object within the bucket. pub object: String, + + /// The version ID of the object from which the tags were removed. + /// + /// If versioning is not enabled on the bucket, this field may be `None`. pub version_id: Option, } #[async_trait] -impl FromS3Response for DeleteObjectTagsResponse { +impl FromS3Response for DeleteObjectTaggingResponse { async fn from_s3response( req: S3Request, resp: Result, diff --git a/src/s3/response/enable_object_legal_hold.rs b/src/s3/response/enable_object_legal_hold.rs deleted file mode 100644 index 668e5d6..0000000 --- a/src/s3/response/enable_object_legal_hold.rs +++ /dev/null @@ -1,53 +0,0 @@ -// 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 crate::s3::error::Error; -use crate::s3::multimap::MultimapExt; -use crate::s3::types::{FromS3Response, S3Request}; -use crate::s3::utils::{take_bucket, take_object}; -use async_trait::async_trait; -use http::HeaderMap; -use std::mem; - -/// Response of -/// [enable_object_legal_hold()](crate::s3::client::Client::enable_object_legal_hold) -/// API -#[derive(Clone, Debug)] -pub struct EnableObjectLegalHoldResponse { - /// Set of HTTP headers returned by the server. - pub headers: HeaderMap, - pub region: String, - pub bucket: String, - pub object: String, - pub version_id: Option, -} - -#[async_trait] -impl FromS3Response for EnableObjectLegalHoldResponse { - async fn from_s3response( - req: S3Request, - resp: Result, - ) -> Result { - let mut resp = resp?; - - Ok(Self { - headers: mem::take(resp.headers_mut()), - region: req.inner_region, - bucket: take_bucket(req.bucket)?, - object: take_object(req.object)?, - version_id: req.query_params.take_version(), - }) - } -} diff --git a/src/s3/response/get_bucket_encryption.rs b/src/s3/response/get_bucket_encryption.rs index 9b8fcd9..3c9602b 100644 --- a/src/s3/response/get_bucket_encryption.rs +++ b/src/s3/response/get_bucket_encryption.rs @@ -22,15 +22,31 @@ use http::HeaderMap; use std::mem; use xmltree::Element; -/// Response of -/// [get_bucket_encryption()](crate::s3::client::Client::get_bucket_encryption) -/// API +/// Response from the [`get_bucket_encryption`](crate::s3::client::Client::get_bucket_encryption) API call, +/// providing the default server-side encryption configuration of an S3 bucket. +/// +/// This configuration determines how Amazon S3 encrypts objects stored in the bucket by default. +/// It can specify encryption using Amazon S3 managed keys (SSE-S3), AWS Key Management Service (SSE-KMS), +/// or dual-layer encryption with AWS KMS keys (DSSE-KMS). +/// +/// For more information, refer to the [AWS S3 GetBucketEncryption API documentation](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketEncryption.html). #[derive(Clone, Debug)] pub struct GetBucketEncryptionResponse { - /// Set of HTTP headers returned by the server. + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, + + /// The AWS region where the bucket resides. pub region: String, + + /// Name of the bucket whose encryption configuration is retrieved. pub bucket: String, + + /// The default server-side encryption configuration of the bucket. + /// + /// This includes the encryption algorithm and, if applicable, the AWS KMS key ID used for encrypting objects. + /// + /// If the bucket has no default encryption configuration, the `get_bucket_encryption` API call may return an error + /// with the code `ServerSideEncryptionConfigurationNotFoundError`. It's advisable to handle this case appropriately in your application. pub config: SseConfig, } diff --git a/src/s3/response/get_bucket_lifecycle.rs b/src/s3/response/get_bucket_lifecycle.rs index 7b9a0db..24d788d 100644 --- a/src/s3/response/get_bucket_lifecycle.rs +++ b/src/s3/response/get_bucket_lifecycle.rs @@ -22,15 +22,30 @@ use http::HeaderMap; use std::mem; use xmltree::Element; -/// Response of -/// [get_bucket_lifecycle()](crate::s3::client::Client::get_bucket_lifecycle) -/// API +/// Response from the [`get_bucket_lifecycle`](crate::s3::client::Client::get_bucket_lifecycle) API call, +/// providing the lifecycle configuration of an S3 bucket. +/// +/// The lifecycle configuration defines rules for managing the lifecycle of objects in the bucket, +/// such as transitioning objects to different storage classes or expiring them after a specified period. +/// +/// For more information, refer to the [AWS S3 GetBucketLifecycleConfiguration API documentation](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketLifecycleConfiguration.html). #[derive(Clone, Debug)] pub struct GetBucketLifecycleResponse { - /// Set of HTTP headers returned by the server. + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, + + /// The AWS region where the bucket resides. pub region: String, + + /// Name of the bucket whose lifecycle configuration is retrieved. pub bucket: String, + + /// The lifecycle configuration of the bucket. + /// + /// This includes a set of rules that define actions applied to objects, such as transitioning + /// them to different storage classes, expiring them, or aborting incomplete multipart uploads. + /// + /// If the bucket has no lifecycle configuration, this field may contain an empty configuration. pub config: LifecycleConfig, } diff --git a/src/s3/response/get_bucket_notification.rs b/src/s3/response/get_bucket_notification.rs index 31c5c60..6bc9325 100644 --- a/src/s3/response/get_bucket_notification.rs +++ b/src/s3/response/get_bucket_notification.rs @@ -22,15 +22,30 @@ use http::HeaderMap; use std::mem; use xmltree::Element; -/// Response of -/// [get_bucket_notification()](crate::s3::client::Client::get_bucket_notification) -/// API +/// Response from the [`get_bucket_notification`](crate::s3::client::Client::get_bucket_notification) API call, +/// providing the notification configuration of an S3 bucket. +/// +/// This configuration specifies the events for which Amazon S3 sends notifications and the destinations +/// (such as Amazon SNS topics, Amazon SQS queues, or AWS Lambda functions) where these notifications are sent. +/// +/// For more information, refer to the [AWS S3 GetBucketNotificationConfiguration API documentation](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketNotificationConfiguration.html). #[derive(Clone, Debug)] pub struct GetBucketNotificationResponse { - /// Set of HTTP headers returned by the server. + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, + + /// The AWS region where the bucket resides. pub region: String, + + /// Name of the bucket whose notification configuration is retrieved. pub bucket: String, + + /// The notification configuration of the bucket. + /// + /// This includes the event types and the destinations (e.g., SNS topics, SQS queues, Lambda functions) + /// configured to receive notifications for those events. + /// + /// If the bucket has no notification configuration, this field may contain an empty configuration. pub config: NotificationConfig, } diff --git a/src/s3/response/get_bucket_policy.rs b/src/s3/response/get_bucket_policy.rs index 7dee74d..3d5ddcc 100644 --- a/src/s3/response/get_bucket_policy.rs +++ b/src/s3/response/get_bucket_policy.rs @@ -20,15 +20,33 @@ use async_trait::async_trait; use http::HeaderMap; use std::mem; -/// Response of -/// [get_bucket_policy()](crate::s3::client::Client::get_bucket_policy) -/// API +/// Response from the [`get_bucket_policy`](crate::s3::client::Client::get_bucket_policy) API call, +/// providing the bucket policy associated with an S3 bucket. +/// +/// The bucket policy is a JSON-formatted string that defines permissions for the bucket, +/// specifying who can access the bucket and what actions they can perform. +/// +/// For more information, refer to the [AWS S3 GetBucketPolicy API documentation](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketPolicy.html). #[derive(Clone, Debug)] pub struct GetBucketPolicyResponse { - /// Set of HTTP headers returned by the server. + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, + + /// The AWS region where the bucket resides. pub region: String, + + /// Name of the bucket whose policy is retrieved. pub bucket: String, + + /// The bucket policy as a JSON-formatted string. + /// + /// This policy defines access permissions for the bucket. It specifies who can access the bucket, + /// what actions they can perform, and under what conditions. + /// + /// For example, a policy might grant read-only access to anonymous users or restrict access to specific IP addresses. + /// + /// Note: If the bucket has no policy, the `get_bucket_policy` API call may return an error + /// with the code `NoSuchBucketPolicy`. It's advisable to handle this case appropriately in your application. pub config: String, } diff --git a/src/s3/response/get_bucket_replication.rs b/src/s3/response/get_bucket_replication.rs index 61fc6a2..b5af7a4 100644 --- a/src/s3/response/get_bucket_replication.rs +++ b/src/s3/response/get_bucket_replication.rs @@ -22,15 +22,29 @@ use http::HeaderMap; use std::mem; use xmltree::Element; -/// Response of -/// [get_bucket_replication()](crate::s3::client::Client::get_bucket_replication) -/// API +/// Response from the [`get_bucket_replication`](crate::s3::client::Client::get_bucket_replication) API call, +/// providing the replication configuration of an S3 bucket. +/// +/// This includes the rules and settings that define how objects in the bucket are replicated to other buckets. +/// +/// For more information, refer to the [AWS S3 GetBucketReplication API documentation](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketReplication.html). #[derive(Clone, Debug)] pub struct GetBucketReplicationResponse { - /// Set of HTTP headers returned by the server. + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, + + /// The AWS region where the bucket resides. pub region: String, + + /// Name of the bucket whose replication configuration is retrieved. pub bucket: String, + + /// The replication configuration of the bucket. + /// + /// This includes the IAM role that Amazon S3 assumes to replicate objects on your behalf, + /// and one or more replication rules that specify the conditions under which objects are replicated. + /// + /// For more details on replication configuration elements, see the [AWS S3 Replication Configuration documentation](https://docs.aws.amazon.com/AmazonS3/latest/userguide/replication-add-config.html). pub config: ReplicationConfig, } diff --git a/src/s3/response/get_bucket_tags.rs b/src/s3/response/get_bucket_tagging.rs similarity index 66% rename from src/s3/response/get_bucket_tags.rs rename to src/s3/response/get_bucket_tagging.rs index 939cedd..a102666 100644 --- a/src/s3/response/get_bucket_tags.rs +++ b/src/s3/response/get_bucket_tagging.rs @@ -23,20 +23,36 @@ use std::collections::HashMap; use std::mem; use xmltree::Element; -/// Response of -/// [get_bucket_tags()](crate::s3::client::Client::get_bucket_tags) -/// API +/// Response from the [`get_bucket_tagging`](crate::s3::client::Client::get_bucket_tagging) API call, +/// providing the set of tags associated with an S3 bucket. +/// +/// Tags are key-value pairs that help organize and manage resources, +/// often used for cost allocation and access control. +/// +/// For more information, refer to the [AWS S3 GetBucketTagging API documentation](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketTagging.html). #[derive(Clone, Debug)] -pub struct GetBucketTagsResponse { - /// Set of HTTP headers returned by the server. +pub struct GetBucketTaggingResponse { + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, + + /// The AWS region where the bucket resides. pub region: String, + + /// Name of the bucket whose tags are retrieved. pub bucket: String, + + /// A collection of tags assigned to the bucket. + /// + /// Each tag is a key-value pair represented as a `HashMap`. + /// If the bucket has no tags, this map will be empty. + /// + /// Note: If the bucket has no tags, the `get_bucket_tags` API call may return an error + /// with the code `NoSuchTagSet`. It's advisable to handle this case appropriately in your application. pub tags: HashMap, } #[async_trait] -impl FromS3Response for GetBucketTagsResponse { +impl FromS3Response for GetBucketTaggingResponse { async fn from_s3response( req: S3Request, resp: Result, diff --git a/src/s3/response/get_bucket_versioning.rs b/src/s3/response/get_bucket_versioning.rs index 34ffd7b..3bcc9d5 100644 --- a/src/s3/response/get_bucket_versioning.rs +++ b/src/s3/response/get_bucket_versioning.rs @@ -23,16 +23,39 @@ use http::HeaderMap; use std::mem; use xmltree::Element; -/// Response of -/// [get_bucket_versioning()](crate::s3::client::Client::get_bucket_versioning) -/// API +/// Response from the [`get_bucket_versioning`](crate::s3::client::Client::get_bucket_versioning) API call, +/// providing the versioning configuration of a bucket. +/// +/// This includes the current versioning status and the MFA (Multi-Factor Authentication) delete setting, +/// if configured. +/// +/// For more information, refer to the [AWS S3 GetBucketVersioning API documentation](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketVersioning.html). #[derive(Clone, Debug)] pub struct GetBucketVersioningResponse { - /// Set of HTTP headers returned by the server. + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, + + /// The AWS region where the bucket resides. pub region: String, + + /// Name of the bucket whose versioning configuration is retrieved. pub bucket: String, + + /// The versioning status of the bucket. + /// + /// - `Some(VersioningStatus::Enabled)`: Versioning is enabled. + /// - `Some(VersioningStatus::Suspended)`: Versioning is suspended. + /// - `None`: Versioning has never been configured for this bucket. pub status: Option, + + /// Indicates whether MFA delete is enabled for the bucket. + /// + /// - `Some(true)`: MFA delete is enabled. + /// - `Some(false)`: MFA delete is disabled. + /// - `None`: MFA delete has never been configured for this bucket. + /// + /// Note: MFA delete adds an extra layer of security by requiring additional authentication + /// for certain operations. For more details, see the [AWS S3 MFA Delete documentation](https://docs.aws.amazon.com/AmazonS3/latest/userguide/MultiFactorAuthenticationDelete.html). pub mfa_delete: Option, } diff --git a/src/s3/response/get_object.rs b/src/s3/response/get_object.rs index 67d410e..7d098dc 100644 --- a/src/s3/response/get_object.rs +++ b/src/s3/response/get_object.rs @@ -25,15 +25,29 @@ use http::HeaderMap; use std::mem; pub struct GetObjectResponse { - /// Set of HTTP headers returned by the server. + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, + + /// The AWS region where the bucket resides. pub region: String, + + /// Name of the bucket containing the object. pub bucket: String, + + /// Key (path) identifying the object within the bucket. pub object: String, - pub version_id: Option, - pub content: ObjectContent, - pub object_size: u64, + + /// Entity tag representing a specific version of the object. pub etag: Option, + + /// Version ID of the object, if versioning is enabled. Value of the `x-amz-version-id` header. + pub version_id: Option, + + /// The content of the object as a stream or byte buffer. + pub content: ObjectContent, + + /// Size of the object in bytes. + pub object_size: u64, } #[async_trait] diff --git a/src/s3/response/is_object_legal_hold_enabled.rs b/src/s3/response/get_object_legal_hold.rs similarity index 80% rename from src/s3/response/is_object_legal_hold_enabled.rs rename to src/s3/response/get_object_legal_hold.rs index e4b202d..295e427 100644 --- a/src/s3/response/is_object_legal_hold_enabled.rs +++ b/src/s3/response/get_object_legal_hold.rs @@ -24,21 +24,31 @@ use std::mem; use xmltree::Element; /// Response of -/// [is_object_legal_hold_enabled()](crate::s3::client::Client::is_object_legal_hold_enabled) +/// [get_object_legal_hold()](crate::s3::client::Client::get_object_legal_hold) /// API #[derive(Clone, Debug)] -pub struct IsObjectLegalHoldEnabledResponse { - /// Set of HTTP headers returned by the server. +pub struct GetObjectLegalHoldResponse { + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, + + /// The AWS region where the bucket resides. pub region: String, + + /// Name of the bucket containing the object. pub bucket: String, + + /// Key (path) identifying the object within the bucket. pub object: String, + + /// Version ID of the object, if versioning is enabled. Value of the `x-amz-version-id` header. pub version_id: Option, + + /// Indicates whether the object legal hold is enabled. pub enabled: bool, } #[async_trait] -impl FromS3Response for IsObjectLegalHoldEnabledResponse { +impl FromS3Response for GetObjectLegalHoldResponse { async fn from_s3response( req: S3Request, resp: Result, diff --git a/src/s3/response/get_object_lock_config.rs b/src/s3/response/get_object_lock_config.rs index ec21242..0da2b74 100644 --- a/src/s3/response/get_object_lock_config.rs +++ b/src/s3/response/get_object_lock_config.rs @@ -22,15 +22,23 @@ use http::HeaderMap; use std::mem; use xmltree::Element; -/// Response of -/// [get_object_lock_config_response()](crate::s3::client::Client::get_object_lock_config_response) -/// API +/// Response from the [`get_object_lock_config`](crate::s3::client::Client::get_object_lock_config) API call, +/// which retrieves the Object Lock configuration of a bucket. +/// +/// This configuration determines the default retention mode and period applied to new objects, +/// helping to enforce write-once-read-many (WORM) protection. #[derive(Clone, Debug)] pub struct GetObjectLockConfigResponse { - /// Set of HTTP headers returned by the server. + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, + + /// The AWS region where the bucket resides. pub region: String, + + /// Name of the bucket for which the Object Lock configuration is retrieved. pub bucket: String, + + /// The Object Lock configuration of the bucket, including retention settings and legal hold status. pub config: ObjectLockConfig, } diff --git a/src/s3/response/object_prompt.rs b/src/s3/response/get_object_prompt.rs similarity index 79% rename from src/s3/response/object_prompt.rs rename to src/s3/response/get_object_prompt.rs index b37dcb6..668968e 100644 --- a/src/s3/response/object_prompt.rs +++ b/src/s3/response/get_object_prompt.rs @@ -20,17 +20,25 @@ use async_trait::async_trait; use http::HeaderMap; use std::mem; -pub struct ObjectPromptResponse { - /// Set of HTTP headers returned by the server. +pub struct GetObjectPromptResponse { + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, + + /// The AWS region where the bucket resides. pub region: String, + + /// Name of the bucket containing the object. pub bucket: String, + + /// Key (path) identifying the object within the bucket. pub object: String, + + /// The prompt response for the object. pub prompt_response: String, } #[async_trait] -impl FromS3Response for ObjectPromptResponse { +impl FromS3Response for GetObjectPromptResponse { async fn from_s3response( req: S3Request, resp: Result, diff --git a/src/s3/response/get_object_retention.rs b/src/s3/response/get_object_retention.rs index 4725d64..929b537 100644 --- a/src/s3/response/get_object_retention.rs +++ b/src/s3/response/get_object_retention.rs @@ -23,19 +23,28 @@ use http::HeaderMap; use std::mem; use xmltree::Element; -/// Response of -/// [set_object_retention_response()](crate::s3::client::Client::set_object_retention_response) -/// API +/// Response of [get_object_retention()](crate::s3::client::Client::get_object_retention) API #[derive(Clone, Debug)] pub struct GetObjectRetentionResponse { - /// Set of HTTP headers returned by the server. + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, + + /// The AWS region where the bucket resides. pub region: String, + + /// Name of the bucket containing the object. pub bucket: String, + /// Key (path) identifying the object within the bucket. pub object: String, + + /// Version ID of the object, if versioning is enabled. Value of the `x-amz-version-id` header. pub version_id: Option, + + /// The retention mode of the object. pub retention_mode: Option, + + /// The date until which the object is retained. pub retain_until_date: Option, } diff --git a/src/s3/response/get_object_tags.rs b/src/s3/response/get_object_tagging.rs similarity index 81% rename from src/s3/response/get_object_tags.rs rename to src/s3/response/get_object_tagging.rs index 5829200..6d55a1c 100644 --- a/src/s3/response/get_object_tags.rs +++ b/src/s3/response/get_object_tagging.rs @@ -25,22 +25,31 @@ use std::mem; use xmltree::Element; /// Response of -/// [get_object_tags()](crate::s3::client::Client::get_object_tags) +/// [get_object_tags()](crate::s3::client::Client::get_object_tagging) /// API #[derive(Clone, Debug)] -pub struct GetObjectTagsResponse { - /// Set of HTTP headers returned by the server. +pub struct GetObjectTaggingResponse { + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, + + /// The AWS region where the bucket resides. pub region: String, + + /// Name of the bucket containing the object. pub bucket: String, + + /// Key (path) identifying the object within the bucket. pub object: String, + /// Version ID of the object, if versioning is enabled. Value of the `x-amz-version-id` header. pub version_id: Option, + + /// Tags associated with the object. pub tags: HashMap, } #[async_trait] -impl FromS3Response for GetObjectTagsResponse { +impl FromS3Response for GetObjectTaggingResponse { async fn from_s3response( req: S3Request, resp: Result, diff --git a/src/s3/response/get_presigned_object_url.rs b/src/s3/response/get_presigned_object_url.rs index 22a3439..40fa633 100644 --- a/src/s3/response/get_presigned_object_url.rs +++ b/src/s3/response/get_presigned_object_url.rs @@ -1,9 +1,18 @@ #[derive(Clone, Debug)] /// Response of [get_presigned_object_url()](crate::s3::client::Client::get_presigned_object_url) API pub struct GetPresignedObjectUrlResponse { + /// The AWS region where the bucket resides. pub region: String, + + /// Name of the bucket containing the object. pub bucket: String, + + /// Key (path) identifying the object within the bucket. pub object: String, + + /// TODO pub version_id: Option, + + /// The presigned URL for the object. pub url: String, } diff --git a/src/s3/response/get_region.rs b/src/s3/response/get_region.rs index ee99460..1435570 100644 --- a/src/s3/response/get_region.rs +++ b/src/s3/response/get_region.rs @@ -28,10 +28,16 @@ use xmltree::Element; /// API #[derive(Clone, Debug)] pub struct GetRegionResponse { - /// Set of HTTP headers returned by the server. + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, + + /// The AWS region where the bucket resides. pub region: String, + + /// Name of the bucket containing the object. pub bucket: String, + + /// The region response for the bucket. pub region_response: String, } diff --git a/src/s3/response/listen_bucket_notification.rs b/src/s3/response/list_bucket_notification.rs similarity index 79% rename from src/s3/response/listen_bucket_notification.rs rename to src/s3/response/list_bucket_notification.rs index bba1ede..177de0a 100644 --- a/src/s3/response/listen_bucket_notification.rs +++ b/src/s3/response/list_bucket_notification.rs @@ -26,20 +26,24 @@ use crate::s3::{ }; /// Response of -/// [listen_bucket_notification()](crate::s3::client::Client::listen_bucket_notification) +/// [list_bucket_notification()](crate::s3::client::Client::list_bucket_notification) /// API #[derive(Debug)] -pub struct ListenBucketNotificationResponse { - /// Set of HTTP headers returned by the server. +pub struct ListBucketNotificationResponse { + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, + + /// The AWS region where the bucket resides. pub region: String, + + /// Name of the bucket containing the object. pub bucket: String, } #[async_trait::async_trait] impl FromS3Response for ( - ListenBucketNotificationResponse, + ListBucketNotificationResponse, Box> + Unpin + Send>, ) { @@ -57,7 +61,7 @@ impl FromS3Response move |mut reader| async move { loop { let mut line = String::new(); - match reader.read_line(&mut line).await { + return match reader.read_line(&mut line).await { Ok(n) => { if n == 0 { return None; @@ -68,16 +72,16 @@ impl FromS3Response } let records_res: Result = serde_json::from_str(s).map_err(|e| e.into()); - return Some((records_res, reader)); + Some((records_res, reader)) } - Err(e) => return Some((Err(e.into()), reader)), - } + Err(e) => Some((Err(e.into()), reader)), + }; } }, )); Ok(( - ListenBucketNotificationResponse { + ListBucketNotificationResponse { headers, region: req.inner_region, bucket: take_bucket(req.bucket)?, diff --git a/src/s3/response/list_buckets.rs b/src/s3/response/list_buckets.rs index 13a65a7..29ea2dc 100644 --- a/src/s3/response/list_buckets.rs +++ b/src/s3/response/list_buckets.rs @@ -25,8 +25,10 @@ use xmltree::Element; /// Response of [list_buckets()](crate::s3::client::Client::list_buckets) API #[derive(Debug, Clone)] pub struct ListBucketsResponse { - /// Set of HTTP headers returned by the server. + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, + + /// the list of buckets that are present in the account. pub buckets: Vec, } diff --git a/src/s3/response/list_objects.rs b/src/s3/response/list_objects.rs index 4287e42..6c354b4 100644 --- a/src/s3/response/list_objects.rs +++ b/src/s3/response/list_objects.rs @@ -188,7 +188,7 @@ fn parse_list_objects_common_prefixes( /// Response of [list_objects_v1()](crate::s3::client::Client::list_objects_v1) S3 API #[derive(Clone, Debug)] pub struct ListObjectsV1Response { - /// Set of HTTP headers returned by the server. + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, pub name: String, pub encoding_type: Option, @@ -242,7 +242,7 @@ impl FromS3Response for ListObjectsV1Response { /// Response of [list_objects_v2()](crate::s3::client::Client::list_objects_v2) S3 API #[derive(Clone, Debug)] pub struct ListObjectsV2Response { - /// Set of HTTP headers returned by the server. + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, pub name: String, pub encoding_type: Option, @@ -303,7 +303,7 @@ impl FromS3Response for ListObjectsV2Response { /// Response of [list_object_versions()](crate::s3::client::Client::list_object_versions) S3 API #[derive(Clone, Debug)] pub struct ListObjectVersionsResponse { - /// Set of HTTP headers returned by the server. + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, pub name: String, pub encoding_type: Option, @@ -360,7 +360,7 @@ impl FromS3Response for ListObjectVersionsResponse { /// Response of [list_objects()](crate::s3::client::Client::list_objects) API #[derive(Clone, Debug, Default)] pub struct ListObjectsResponse { - /// Set of HTTP headers returned by the server. + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, pub name: String, pub encoding_type: Option, diff --git a/src/s3/response/set_bucket_encryption.rs b/src/s3/response/put_bucket_encryption.rs similarity index 83% rename from src/s3/response/set_bucket_encryption.rs rename to src/s3/response/put_bucket_encryption.rs index 0d3db33..1e8186d 100644 --- a/src/s3/response/set_bucket_encryption.rs +++ b/src/s3/response/put_bucket_encryption.rs @@ -23,19 +23,25 @@ use std::mem; use xmltree::Element; /// Response of -/// [set_bucket_encryption()](crate::s3::client::Client::set_bucket_encryption) +/// [put_bucket_encryption()](crate::s3::client::Client::put_bucket_encryption) /// API #[derive(Clone, Debug)] -pub struct SetBucketEncryptionResponse { - /// Set of HTTP headers returned by the server. +pub struct PutBucketEncryptionResponse { + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, + + /// The AWS region where the bucket resides. pub region: String, + + /// Name of the bucket containing the object. pub bucket: String, + + /// Server-side encryption configuration. pub config: SseConfig, } #[async_trait] -impl FromS3Response for SetBucketEncryptionResponse { +impl FromS3Response for PutBucketEncryptionResponse { async fn from_s3response( req: S3Request, resp: Result, diff --git a/src/s3/response/set_bucket_lifecycle.rs b/src/s3/response/put_bucket_lifecycle.rs similarity index 76% rename from src/s3/response/set_bucket_lifecycle.rs rename to src/s3/response/put_bucket_lifecycle.rs index c5b018f..135f109 100644 --- a/src/s3/response/set_bucket_lifecycle.rs +++ b/src/s3/response/put_bucket_lifecycle.rs @@ -20,17 +20,21 @@ use async_trait::async_trait; use http::HeaderMap; use std::mem; -/// Response of [set_bucket_lifecycle()](crate::s3::client::Client::set_bucket_lifecycle) API +/// Response of [put_bucket_lifecycle()](crate::s3::client::Client::put_bucket_lifecycle) API #[derive(Debug)] -pub struct SetBucketLifecycleResponse { - /// Set of HTTP headers returned by the server. +pub struct PutBucketLifecycleResponse { + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, + + /// The AWS region where the bucket resides. pub region: String, + + /// Name of the bucket containing the object. pub bucket: String, } #[async_trait] -impl FromS3Response for SetBucketLifecycleResponse { +impl FromS3Response for PutBucketLifecycleResponse { async fn from_s3response( req: S3Request, resp: Result, diff --git a/src/s3/response/put_bucket_notification.rs b/src/s3/response/put_bucket_notification.rs new file mode 100644 index 0000000..564e2f0 --- /dev/null +++ b/src/s3/response/put_bucket_notification.rs @@ -0,0 +1,50 @@ +// 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 crate::s3::error::Error; +use crate::s3::types::{FromS3Response, S3Request}; +use crate::s3::utils::take_bucket; +use async_trait::async_trait; +use http::HeaderMap; +use std::mem; + +/// Response of [put_bucket_notification()](crate::s3::client::Client::put_bucket_notification) API +#[derive(Debug)] +pub struct PutBucketNotificationResponse { + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. + pub headers: HeaderMap, + + /// The AWS region where the bucket resides. + pub region: String, + + /// Name of the bucket containing the object. + pub bucket: String, +} + +#[async_trait] +impl FromS3Response for PutBucketNotificationResponse { + async fn from_s3response( + req: S3Request, + resp: Result, + ) -> Result { + let mut resp = resp?; + + Ok(Self { + headers: mem::take(resp.headers_mut()), + region: req.inner_region, + bucket: take_bucket(req.bucket)?, + }) + } +} diff --git a/src/s3/response/set_bucket_replication.rs b/src/s3/response/put_bucket_policy.rs similarity index 77% rename from src/s3/response/set_bucket_replication.rs rename to src/s3/response/put_bucket_policy.rs index 9c27bae..09af3c3 100644 --- a/src/s3/response/set_bucket_replication.rs +++ b/src/s3/response/put_bucket_policy.rs @@ -20,17 +20,21 @@ use async_trait::async_trait; use http::HeaderMap; use std::mem; -/// Response of [set_bucket_replication()](crate::s3::client::Client::set_bucket_replication) API +/// Response of [put_bucket_policy()](crate::s3::client::Client::put_bucket_policy) API #[derive(Debug)] -pub struct SetBucketReplicationResponse { - /// Set of HTTP headers returned by the server. +pub struct PutBucketPolicyResponse { + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, + + /// The AWS region where the bucket resides. pub region: String, + + /// Name of the bucket containing the object. pub bucket: String, } #[async_trait] -impl FromS3Response for SetBucketReplicationResponse { +impl FromS3Response for PutBucketPolicyResponse { async fn from_s3response( req: S3Request, resp: Result, diff --git a/src/s3/response/set_bucket_policy.rs b/src/s3/response/put_bucket_replication.rs similarity index 76% rename from src/s3/response/set_bucket_policy.rs rename to src/s3/response/put_bucket_replication.rs index a62258c..fdf800b 100644 --- a/src/s3/response/set_bucket_policy.rs +++ b/src/s3/response/put_bucket_replication.rs @@ -20,17 +20,21 @@ use async_trait::async_trait; use http::HeaderMap; use std::mem; -/// Response of [set_bucket_policy()](crate::s3::client::Client::set_bucket_policy) API +/// Response of [put_bucket_replication()](crate::s3::client::Client::put_bucket_replication) API #[derive(Debug)] -pub struct SetBucketPolicyResponse { - /// Set of HTTP headers returned by the server. +pub struct PutBucketReplicationResponse { + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, + + /// The AWS region where the bucket resides. pub region: String, + + /// Name of the bucket containing the object. pub bucket: String, } #[async_trait] -impl FromS3Response for SetBucketPolicyResponse { +impl FromS3Response for PutBucketReplicationResponse { async fn from_s3response( req: S3Request, resp: Result, diff --git a/src/s3/response/delete_bucket_tags.rs b/src/s3/response/put_bucket_tagging.rs similarity index 78% rename from src/s3/response/delete_bucket_tags.rs rename to src/s3/response/put_bucket_tagging.rs index f5b8666..b8f1431 100644 --- a/src/s3/response/delete_bucket_tags.rs +++ b/src/s3/response/put_bucket_tagging.rs @@ -21,18 +21,22 @@ use http::HeaderMap; use std::mem; /// Response of -/// [delete_bucket_tags()](crate::s3::client::Client::delete_bucket_tags) +/// [put_bucket_tagging()](crate::s3::client::Client::put_bucket_tagging) /// API #[derive(Clone, Debug)] -pub struct DeleteBucketTagsResponse { - /// Set of HTTP headers returned by the server. +pub struct PutBucketTaggingResponse { + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, + + /// The AWS region where the bucket resides. pub region: String, + + /// Name of the bucket containing the object. pub bucket: String, } #[async_trait] -impl FromS3Response for DeleteBucketTagsResponse { +impl FromS3Response for PutBucketTaggingResponse { async fn from_s3response( req: S3Request, resp: Result, diff --git a/src/s3/response/set_bucket_notification.rs b/src/s3/response/put_bucket_versioning.rs similarity index 76% rename from src/s3/response/set_bucket_notification.rs rename to src/s3/response/put_bucket_versioning.rs index 0efb750..dc9051a 100644 --- a/src/s3/response/set_bucket_notification.rs +++ b/src/s3/response/put_bucket_versioning.rs @@ -20,17 +20,21 @@ use async_trait::async_trait; use http::HeaderMap; use std::mem; -/// Response of [set_bucket_notification()](crate::s3::client::Client::set_bucket_notification) API +/// Response of [put_bucket_versioning()](crate::s3::client::Client::put_bucket_versioning) API #[derive(Debug)] -pub struct SetBucketNotificationResponse { - /// Set of HTTP headers returned by the server. +pub struct PutBucketVersioningResponse { + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, + + /// The AWS region where the bucket resides. pub region: String, + + /// Name of the bucket containing the object. pub bucket: String, } #[async_trait] -impl FromS3Response for SetBucketNotificationResponse { +impl FromS3Response for PutBucketVersioningResponse { async fn from_s3response( req: S3Request, resp: Result, diff --git a/src/s3/response/put_object.rs b/src/s3/response/put_object.rs index 1e379cf..d28d159 100644 --- a/src/s3/response/put_object.rs +++ b/src/s3/response/put_object.rs @@ -29,7 +29,7 @@ use crate::s3::{ /// Response of [put_object_api()](crate::s3::client::Client::put_object) API #[derive(Debug, Clone)] pub struct PutObjectResponse { - /// Set of HTTP headers returned by the server. + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, pub bucket: String, pub object: String, @@ -71,7 +71,7 @@ impl FromS3Response for PutObjectResponse { #[derive(Debug, Clone)] pub struct CreateMultipartUploadResponse { - /// Set of HTTP headers returned by the server. + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, pub region: String, pub bucket: String, @@ -111,12 +111,24 @@ pub type UploadPartResponse = PutObjectResponse; #[derive(Debug, Clone)] pub struct PutObjectContentResponse { - /// Set of HTTP headers returned by the server. + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, - pub bucket: String, - pub object: String, + + /// The AWS region where the bucket resides. pub region: String, + + /// Name of the bucket containing the object. + pub bucket: String, + + /// Key (path) identifying the object within the bucket. + pub object: String, + + /// Size of the object in bytes. pub object_size: u64, + + /// Entity tag representing a specific version of the object. pub etag: String, + + /// Version ID of the object, if versioning is enabled. Value of the `x-amz-version-id` header. pub version_id: Option, } diff --git a/src/s3/response/disable_object_legal_hold.rs b/src/s3/response/put_object_legal_hold.rs similarity index 58% rename from src/s3/response/disable_object_legal_hold.rs rename to src/s3/response/put_object_legal_hold.rs index 049bc1e..6f06c83 100644 --- a/src/s3/response/disable_object_legal_hold.rs +++ b/src/s3/response/put_object_legal_hold.rs @@ -21,21 +21,35 @@ use async_trait::async_trait; use http::HeaderMap; use std::mem; -/// Response of -/// [disable_object_legal_hold()](crate::s3::client::Client::disable_object_legal_hold) -/// API +/// Response from the [`put_object_legal_hold`](crate::s3::client::Client::put_object_legal_hold) API call, +/// indicating that a legal hold has been successfully removed from a specific object version in an S3 bucket. +/// +/// Removing a legal hold allows the specified object version to be deleted or overwritten, subject to the bucket's +/// retention configuration and permissions. +/// +/// For more information, refer to the [AWS S3 PutObjectLegalHold API documentation](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObjectLegalHold.html). #[derive(Clone, Debug)] -pub struct DisableObjectLegalHoldResponse { - /// Set of HTTP headers returned by the server. +pub struct PutObjectLegalHoldResponse { + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, + + /// The AWS region where the bucket resides. pub region: String, + + /// Name of the bucket containing the object. pub bucket: String, + + /// Key (name) identifying the object within the bucket. pub object: String, + + /// The version ID of the object from which the legal hold was removed. + /// + /// If versioning is not enabled on the bucket, this field may be `None`. pub version_id: Option, } #[async_trait] -impl FromS3Response for DisableObjectLegalHoldResponse { +impl FromS3Response for PutObjectLegalHoldResponse { async fn from_s3response( req: S3Request, resp: Result, diff --git a/src/s3/response/set_bucket_tags.rs b/src/s3/response/put_object_lock_config.rs similarity index 77% rename from src/s3/response/set_bucket_tags.rs rename to src/s3/response/put_object_lock_config.rs index 88d8b93..30d7550 100644 --- a/src/s3/response/set_bucket_tags.rs +++ b/src/s3/response/put_object_lock_config.rs @@ -21,18 +21,22 @@ use http::HeaderMap; use std::mem; /// Response of -/// [set_bucket_tags()](crate::s3::client::Client::set_bucket_tags) +/// [put_object_lock_config()](crate::s3::client::Client::put_object_lock_config) /// API #[derive(Clone, Debug)] -pub struct SetBucketTagsResponse { - /// Set of HTTP headers returned by the server. +pub struct PutObjectLockConfigResponse { + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, + + /// The AWS region where the bucket resides. pub region: String, + + /// Name of the bucket containing the object. pub bucket: String, } #[async_trait] -impl FromS3Response for SetBucketTagsResponse { +impl FromS3Response for PutObjectLockConfigResponse { async fn from_s3response( req: S3Request, resp: Result, diff --git a/src/s3/response/set_object_tags.rs b/src/s3/response/put_object_retention.rs similarity index 74% rename from src/s3/response/set_object_tags.rs rename to src/s3/response/put_object_retention.rs index 57e18d5..c04bb36 100644 --- a/src/s3/response/set_object_tags.rs +++ b/src/s3/response/put_object_retention.rs @@ -22,21 +22,28 @@ use http::HeaderMap; use std::mem; /// Response of -/// [set_object_tags()](crate::s3::client::Client::set_object_tags) +/// [put_object_retention()](crate::s3::client::Client::put_object_retention) /// API #[derive(Clone, Debug)] -pub struct SetObjectTagsResponse { - /// Set of HTTP headers returned by the server. +pub struct PutObjectRetentionResponse { + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, + + /// The AWS region where the bucket resides. pub region: String, + + /// Name of the bucket containing the object. pub bucket: String, + /// Key (path) identifying the object within the bucket. pub object: String, + + /// Version ID of the object, if versioning is enabled. Value of the `x-amz-version-id` header. pub version_id: Option, } #[async_trait] -impl FromS3Response for SetObjectTagsResponse { +impl FromS3Response for PutObjectRetentionResponse { async fn from_s3response( req: S3Request, resp: Result, diff --git a/src/s3/response/set_object_retention.rs b/src/s3/response/put_object_tagging.rs similarity index 74% rename from src/s3/response/set_object_retention.rs rename to src/s3/response/put_object_tagging.rs index 4831c0b..51e333a 100644 --- a/src/s3/response/set_object_retention.rs +++ b/src/s3/response/put_object_tagging.rs @@ -22,21 +22,28 @@ use http::HeaderMap; use std::mem; /// Response of -/// [set_object_retention_response()](crate::s3::client::Client::set_object_retention_response) +/// [put_object_tagging()](crate::s3::client::Client::put_object_tagging) /// API #[derive(Clone, Debug)] -pub struct SetObjectRetentionResponse { - /// Set of HTTP headers returned by the server. +pub struct PutObjectTaggingResponse { + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, + + /// The AWS region where the bucket resides. pub region: String, + + /// Name of the bucket containing the object. pub bucket: String, + /// Key (path) identifying the object within the bucket. pub object: String, + + /// Version ID of the object, if versioning is enabled. Value of the `x-amz-version-id` header. pub version_id: Option, } #[async_trait] -impl FromS3Response for SetObjectRetentionResponse { +impl FromS3Response for PutObjectTaggingResponse { async fn from_s3response( req: S3Request, resp: Result, diff --git a/src/s3/response/remove_objects.rs b/src/s3/response/remove_objects.rs index 8c124c0..926333c 100644 --- a/src/s3/response/remove_objects.rs +++ b/src/s3/response/remove_objects.rs @@ -29,10 +29,12 @@ use crate::s3::{ #[derive(Debug, Clone)] pub struct RemoveObjectResponse { - /// Set of HTTP headers returned by the server. + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, + /// Value of the `x-amz-delete-marker` header. pub is_delete_marker: bool, + /// If a delete marker was created, this field will contain the version_id /// of the delete marker. Value of the `x-amz-version-id` header. pub version_id: Option, @@ -82,13 +84,13 @@ pub struct DeletedObject { } /// Response of -/// [delete_objects()](crate::s3::client_core::ClientCore::delete_objects) +/// [delete_objects()](crate::s3::client::Client::delete_objects) /// S3 API. It is also returned by the /// [remove_objects()](crate::s3::client::Client::remove_objects) API in the /// form of a stream. #[derive(Clone, Debug)] pub struct RemoveObjectsResponse { - /// Set of HTTP headers returned by the server. + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, pub result: Vec, } diff --git a/src/s3/response/select_object_content.rs b/src/s3/response/select_object_content.rs index 07ee6b0..a88fcd7 100644 --- a/src/s3/response/select_object_content.rs +++ b/src/s3/response/select_object_content.rs @@ -29,11 +29,18 @@ use xmltree::Element; /// Response of [select_object_content()](crate::s3::client::Client::select_object_content) API #[derive(Debug)] pub struct SelectObjectContentResponse { - /// Set of HTTP headers returned by the server. + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, + + /// The AWS region where the bucket resides. pub region: String, + + /// Name of the bucket containing the object. pub bucket: String, + + /// Key (path) identifying the object within the bucket. pub object: String, + pub progress: SelectProgress, resp: reqwest::Response, diff --git a/src/s3/response/set_bucket_versioning.rs b/src/s3/response/set_bucket_versioning.rs deleted file mode 100644 index 26d645e..0000000 --- a/src/s3/response/set_bucket_versioning.rs +++ /dev/null @@ -1,46 +0,0 @@ -// 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 crate::s3::error::Error; -use crate::s3::types::{FromS3Response, S3Request}; -use crate::s3::utils::take_bucket; -use async_trait::async_trait; -use http::HeaderMap; -use std::mem; - -/// Response of [set_bucket_versioning()](crate::s3::client::Client::set_bucket_versioning) API -#[derive(Debug)] -pub struct SetBucketVersioningResponse { - /// Set of HTTP headers returned by the server. - pub headers: HeaderMap, - pub region: String, - pub bucket: String, -} - -#[async_trait] -impl FromS3Response for SetBucketVersioningResponse { - async fn from_s3response( - req: S3Request, - resp: Result, - ) -> Result { - let mut resp = resp?; - - Ok(Self { - headers: mem::take(resp.headers_mut()), - region: req.inner_region, - bucket: take_bucket(req.bucket)?, - }) - } -} diff --git a/src/s3/response/stat_object.rs b/src/s3/response/stat_object.rs index ba85b33..a9a2864 100644 --- a/src/s3/response/stat_object.rs +++ b/src/s3/response/stat_object.rs @@ -27,21 +27,46 @@ use std::collections::HashMap; use std::mem; #[derive(Debug)] -/// Response of [stat_object()](crate::s3::client::Client::stat_object) API +/// Response from the [`stat_object`](crate::s3::client::Client::stat_object) API call, +/// providing metadata about an object stored in S3 or a compatible service. pub struct StatObjectResponse { - /// Set of HTTP headers returned by the server. + /// HTTP headers returned by the server, containing metadata such as `Content-Type`, `ETag`, etc. pub headers: HeaderMap, + + /// The AWS region where the bucket resides. pub region: String, + + /// Name of the bucket containing the object. pub bucket: String, + + /// Key (path) identifying the object within the bucket. pub object: String, + + /// Size of the object in bytes. pub size: u64, + + /// Entity tag representing a specific version of the object. pub etag: String, + + /// Version ID of the object, if versioning is enabled. pub version_id: Option, + + /// Timestamp indicating when the object was last modified. pub last_modified: Option, + + /// Retention mode applied to the object (e.g., Governance, Compliance). pub retention_mode: Option, + + /// Date until which the object is retained under the specified retention mode. pub retention_retain_until_date: Option, + + /// Indicates if a legal hold is in place for the object. pub legal_hold: Option, + + /// Indicates if the object is a delete marker (in versioned buckets). pub delete_marker: Option, + + /// Custom user-defined metadata associated with the object. pub user_metadata: HashMap, } diff --git a/src/s3/segmented_bytes.rs b/src/s3/segmented_bytes.rs index 5aad3cc..1e0069c 100644 --- a/src/s3/segmented_bytes.rs +++ b/src/s3/segmented_bytes.rs @@ -61,15 +61,7 @@ impl SegmentedBytes { } } - pub fn into_iter(self) -> SegmentedBytesIntoIterator { - SegmentedBytesIntoIterator { - sb: self, - current_segment: 0, - current_segment_index: 0, - } - } - - /// Copy all the content into a single [Bytes](bytes::Bytes) object. + /// Copy all the content into a single [Bytes] object. /// /// ⚠️ This function is slow and intended for testing/debugging only. /// Do not use in performance-critical code. diff --git a/src/s3/signer.rs b/src/s3/signer.rs index 73218a0..348e87d 100644 --- a/src/s3/signer.rs +++ b/src/s3/signer.rs @@ -66,16 +66,8 @@ fn get_canonical_request_hash( signed_headers: &str, content_sha256: &str, ) -> String { - // CanonicalRequest = - // HTTPRequestMethod + '\n' + - // CanonicalURI + '\n' + - // CanonicalQueryString + '\n' + - // CanonicalHeaders + '\n\n' + - // SignedHeaders + '\n' + - // HexEncode(Hash(RequestPayload)) let canonical_request = format!( - "{}\n{}\n{}\n{}\n\n{}\n{}", - method, uri, query_string, headers, signed_headers, content_sha256 + "{method}\n{uri}\n{query_string}\n{headers}\n\n{signed_headers}\n{content_sha256}", ); sha256_hash(canonical_request.as_bytes()) } @@ -114,8 +106,7 @@ fn get_authorization( signature: &str, ) -> String { format!( - "AWS4-HMAC-SHA256 Credential={}/{}, SignedHeaders={}, Signature={}", - access_key, scope, signed_headers, signature + "AWS4-HMAC-SHA256 Credential={access_key}/{scope}, SignedHeaders={signed_headers}, Signature={signature}", ) } diff --git a/src/s3/utils.rs b/src/s3/utils.rs index 0a80d26..9aa52f2 100644 --- a/src/s3/utils.rs +++ b/src/s3/utils.rs @@ -276,22 +276,19 @@ pub fn check_bucket_name(bucket_name: impl AsRef, strict: bool) -> Result<( if bucket_name.contains("..") || bucket_name.contains(".-") || bucket_name.contains("-.") { return Err(Error::InvalidBucketName(format!( - "bucket name ('{}') contains invalid successive characters '..', '.-' or '-.'", - bucket_name + "bucket name ('{bucket_name}') contains invalid successive characters '..', '.-' or '-.'", ))); } if strict { if !VALID_BUCKET_NAME_STRICT_REGEX.is_match(bucket_name) { return Err(Error::InvalidBucketName(format!( - "bucket name ('{}') does not follow S3 standards strictly", - bucket_name + "bucket name ('{bucket_name}') does not follow S3 standards strictly", ))); } } else if !VALID_BUCKET_NAME_REGEX.is_match(bucket_name) { return Err(Error::InvalidBucketName(format!( - "bucket name ('{}') does not follow S3 standards", - bucket_name + "bucket name ('{bucket_name}') does not follow S3 standards" ))); } @@ -312,9 +309,9 @@ pub fn check_object_name(object_name: impl AsRef) -> Result<(), Error> { pub fn get_text(element: &Element, tag: &str) -> Result { Ok(element .get_child(tag) - .ok_or(Error::XmlError(format!("<{}> tag not found", tag)))? + .ok_or(Error::XmlError(format!("<{tag}> tag not found")))? .get_text() - .ok_or(Error::XmlError(format!("text of <{}> tag not found", tag)))? + .ok_or(Error::XmlError(format!("text of <{tag}> tag not found")))? .to_string()) } @@ -508,13 +505,13 @@ pub mod xml { let i = self .child_element_index .get_first(tag) - .ok_or(Error::XmlError(format!("<{}> tag not found", tag)))?; + .ok_or(Error::XmlError(format!("<{tag}> tag not found")))?; self.inner.children[i] .as_element() .unwrap() .get_text() .map(|x| x.to_string()) - .ok_or(Error::XmlError(format!("text of <{}> tag not found", tag))) + .ok_or(Error::XmlError(format!("text of <{tag}> tag not found"))) } // Returns all children with given tag along with their index. diff --git a/tests/test_bucket_create_delete.rs b/tests/test_bucket_create_delete.rs index 6900bb9..27b8dc6 100644 --- a/tests/test_bucket_create_delete.rs +++ b/tests/test_bucket_create_delete.rs @@ -15,7 +15,7 @@ use minio::s3::client::DEFAULT_REGION; use minio::s3::error::{Error, ErrorCode}; -use minio::s3::response::{BucketExistsResponse, MakeBucketResponse, RemoveBucketResponse}; +use minio::s3::response::{BucketExistsResponse, CreateBucketResponse, DeleteBucketResponse}; use minio::s3::types::S3Api; use minio_common::test_context::TestContext; use minio_common::utils::rand_bucket_name; @@ -26,7 +26,7 @@ async fn bucket_create() { let bucket_name = rand_bucket_name(); // try to create a bucket that does not exist - let resp: MakeBucketResponse = ctx.client.make_bucket(&bucket_name).send().await.unwrap(); + let resp: CreateBucketResponse = ctx.client.create_bucket(&bucket_name).send().await.unwrap(); assert_eq!(resp.bucket, bucket_name); assert_eq!(resp.region, DEFAULT_REGION); @@ -37,7 +37,8 @@ async fn bucket_create() { assert_eq!(resp.region, DEFAULT_REGION); // try to create a bucket that already exists - let resp: Result = ctx.client.make_bucket(&bucket_name).send().await; + let resp: Result = + ctx.client.create_bucket(&bucket_name).send().await; match resp { Ok(_) => panic!("Bucket already exists, but was created again"), Err(Error::S3Error(e)) if e.code == ErrorCode::BucketAlreadyOwnedByYou => { @@ -53,8 +54,8 @@ async fn bucket_delete() { let bucket_name = rand_bucket_name(); // try to remove a bucket that does not exist - let resp: Result = - ctx.client.remove_bucket(&bucket_name).send().await; + let resp: Result = + ctx.client.delete_bucket(&bucket_name).send().await; match resp { Ok(_) => panic!("Bucket does not exist, but was removed"), Err(Error::S3Error(e)) if e.code == ErrorCode::NoSuchBucket => { @@ -64,7 +65,7 @@ async fn bucket_delete() { } // create a new bucket - let resp: MakeBucketResponse = ctx.client.make_bucket(&bucket_name).send().await.unwrap(); + let resp: CreateBucketResponse = ctx.client.create_bucket(&bucket_name).send().await.unwrap(); assert_eq!(resp.bucket, bucket_name); assert_eq!(resp.region, DEFAULT_REGION); @@ -75,7 +76,7 @@ async fn bucket_delete() { assert_eq!(resp.region, DEFAULT_REGION); // try to remove a bucket that exists - let resp: RemoveBucketResponse = ctx.client.remove_bucket(&bucket_name).send().await.unwrap(); + let resp: DeleteBucketResponse = ctx.client.delete_bucket(&bucket_name).send().await.unwrap(); assert_eq!(resp.bucket, bucket_name); assert_eq!(resp.region, DEFAULT_REGION); diff --git a/tests/test_bucket_encryption.rs b/tests/test_bucket_encryption.rs index 4e6e2d3..947cb30 100644 --- a/tests/test_bucket_encryption.rs +++ b/tests/test_bucket_encryption.rs @@ -15,7 +15,7 @@ use minio::s3::client::DEFAULT_REGION; use minio::s3::response::{ - DeleteBucketEncryptionResponse, GetBucketEncryptionResponse, SetBucketEncryptionResponse, + DeleteBucketEncryptionResponse, GetBucketEncryptionResponse, PutBucketEncryptionResponse, }; use minio::s3::types::{S3Api, SseConfig}; use minio_common::test_context::TestContext; @@ -29,9 +29,9 @@ async fn bucket_encryption() { if false { // TODO this gives a runtime error - let resp: SetBucketEncryptionResponse = ctx + let resp: PutBucketEncryptionResponse = ctx .client - .set_bucket_encryption(&bucket_name) + .put_bucket_encryption(&bucket_name) .sse_config(config.clone()) .send() .await diff --git a/tests/test_bucket_exists.rs b/tests/test_bucket_exists.rs index 3aa3dd1..eb43800 100644 --- a/tests/test_bucket_exists.rs +++ b/tests/test_bucket_exists.rs @@ -14,7 +14,7 @@ // limitations under the License. use minio::s3::client::DEFAULT_REGION; -use minio::s3::response::{BucketExistsResponse, RemoveBucketResponse}; +use minio::s3::response::{BucketExistsResponse, DeleteBucketResponse}; use minio::s3::types::S3Api; use minio_common::test_context::TestContext; @@ -28,7 +28,7 @@ async fn bucket_exists() { assert_eq!(resp.bucket, bucket_name); assert_eq!(resp.region, DEFAULT_REGION); - let resp: RemoveBucketResponse = ctx.client.remove_bucket(&bucket_name).send().await.unwrap(); + let resp: DeleteBucketResponse = ctx.client.delete_bucket(&bucket_name).send().await.unwrap(); assert_eq!(resp.bucket, bucket_name); assert_eq!(resp.region, DEFAULT_REGION); diff --git a/tests/test_bucket_lifecycle.rs b/tests/test_bucket_lifecycle.rs index 66035ab..44c9ba1 100644 --- a/tests/test_bucket_lifecycle.rs +++ b/tests/test_bucket_lifecycle.rs @@ -15,7 +15,7 @@ use minio::s3::client::DEFAULT_REGION; use minio::s3::response::{ - DeleteBucketLifecycleResponse, GetBucketLifecycleResponse, SetBucketLifecycleResponse, + DeleteBucketLifecycleResponse, GetBucketLifecycleResponse, PutBucketLifecycleResponse, }; use minio::s3::types::{LifecycleConfig, S3Api}; use minio_common::example::create_bucket_lifecycle_config_examples; @@ -28,9 +28,9 @@ async fn bucket_lifecycle() { let config: LifecycleConfig = create_bucket_lifecycle_config_examples(); - let resp: SetBucketLifecycleResponse = ctx + let resp: PutBucketLifecycleResponse = ctx .client - .set_bucket_lifecycle(&bucket_name) + .put_bucket_lifecycle(&bucket_name) .life_cycle_config(config.clone()) .send() .await diff --git a/tests/test_bucket_notification.rs b/tests/test_bucket_notification.rs index 8132f52..00d7b83 100644 --- a/tests/test_bucket_notification.rs +++ b/tests/test_bucket_notification.rs @@ -15,7 +15,7 @@ use minio::s3::client::DEFAULT_REGION; use minio::s3::response::{ - DeleteBucketNotificationResponse, GetBucketNotificationResponse, SetBucketNotificationResponse, + DeleteBucketNotificationResponse, GetBucketNotificationResponse, PutBucketNotificationResponse, }; use minio::s3::types::{NotificationConfig, S3Api}; use minio_common::example::create_bucket_notification_config_example; @@ -30,9 +30,9 @@ async fn test_bucket_notification() { let config: NotificationConfig = create_bucket_notification_config_example(); - let resp: SetBucketNotificationResponse = ctx + let resp: PutBucketNotificationResponse = ctx .client - .set_bucket_notification(&bucket_name) + .put_bucket_notification(&bucket_name) .notification_config(config.clone()) .send() .await diff --git a/tests/test_bucket_policy.rs b/tests/test_bucket_policy.rs index c9124e6..4db77c8 100644 --- a/tests/test_bucket_policy.rs +++ b/tests/test_bucket_policy.rs @@ -15,7 +15,7 @@ use minio::s3::client::DEFAULT_REGION; use minio::s3::response::{ - DeleteBucketPolicyResponse, GetBucketPolicyResponse, SetBucketPolicyResponse, + DeleteBucketPolicyResponse, GetBucketPolicyResponse, PutBucketPolicyResponse, }; use minio::s3::types::S3Api; use minio_common::example::create_bucket_policy_config_example; @@ -28,9 +28,9 @@ async fn bucket_policy() { let config: String = create_bucket_policy_config_example(&bucket_name); - let resp: SetBucketPolicyResponse = ctx + let resp: PutBucketPolicyResponse = ctx .client - .set_bucket_policy(&bucket_name) + .put_bucket_policy(&bucket_name) .config(config.clone()) .send() .await diff --git a/tests/test_bucket_replication.rs b/tests/test_bucket_replication.rs index c6db2c0..67a8eb1 100644 --- a/tests/test_bucket_replication.rs +++ b/tests/test_bucket_replication.rs @@ -18,7 +18,7 @@ use minio::s3::client::DEFAULT_REGION; use minio::s3::error::{Error, ErrorCode}; use minio::s3::response::{ DeleteBucketReplicationResponse, GetBucketReplicationResponse, GetBucketVersioningResponse, - SetBucketPolicyResponse, SetBucketReplicationResponse, SetBucketVersioningResponse, + PutBucketPolicyResponse, PutBucketReplicationResponse, PutBucketVersioningResponse, }; use minio::s3::types::{ReplicationConfig, S3Api}; use minio_common::example::{ @@ -39,9 +39,9 @@ async fn bucket_replication_s3() { let (bucket_name2, _cleanup2) = ctx2.create_bucket_helper().await; { - let resp: SetBucketVersioningResponse = ctx + let resp: PutBucketVersioningResponse = ctx .client - .set_bucket_versioning(&bucket_name) + .put_bucket_versioning(&bucket_name) .versioning_status(VersioningStatus::Enabled) .send() .await @@ -49,9 +49,9 @@ async fn bucket_replication_s3() { assert_eq!(resp.bucket, bucket_name); assert_eq!(resp.region, DEFAULT_REGION); - let resp: SetBucketVersioningResponse = ctx + let resp: PutBucketVersioningResponse = ctx .client - .set_bucket_versioning(&bucket_name2) + .put_bucket_versioning(&bucket_name2) .versioning_status(VersioningStatus::Enabled) .send() .await @@ -72,17 +72,17 @@ async fn bucket_replication_s3() { if false { //TODO: to allow replication policy needs to be applied, but this fails let config: String = create_bucket_policy_config_example_for_replication(); - let _resp: SetBucketPolicyResponse = ctx + let _resp: PutBucketPolicyResponse = ctx .client - .set_bucket_policy(&bucket_name) + .put_bucket_policy(&bucket_name) .config(config.clone()) .send() .await .unwrap(); - let _resp: SetBucketPolicyResponse = ctx + let _resp: PutBucketPolicyResponse = ctx .client - .set_bucket_policy(&bucket_name2) + .put_bucket_policy(&bucket_name2) .config(config.clone()) .send() .await @@ -95,9 +95,9 @@ async fn bucket_replication_s3() { //TODO setup permissions that allow replication // TODO panic: called `Result::unwrap()` on an `Err` value: S3Error(ErrorResponse { code: "XMinioAdminRemoteTargetNotFoundError", message: "The remote target does not exist", - let resp: SetBucketReplicationResponse = ctx + let resp: PutBucketReplicationResponse = ctx .client - .set_bucket_replication(&bucket_name) + .put_bucket_replication(&bucket_name) .replication_config(config.clone()) .send() .await @@ -146,9 +146,9 @@ async fn bucket_replication_s3express() { let config: ReplicationConfig = create_bucket_replication_config_example(&bucket_name); - let resp: Result = ctx + let resp: Result = ctx .client - .set_bucket_replication(&bucket_name) + .put_bucket_replication(&bucket_name) .replication_config(config.clone()) .send() .await; diff --git a/tests/test_bucket_tags.rs b/tests/test_bucket_tags.rs index 9f018ba..3da68f9 100644 --- a/tests/test_bucket_tags.rs +++ b/tests/test_bucket_tags.rs @@ -15,7 +15,9 @@ use minio::s3::client::DEFAULT_REGION; use minio::s3::error::{Error, ErrorCode}; -use minio::s3::response::{DeleteBucketTagsResponse, GetBucketTagsResponse, SetBucketTagsResponse}; +use minio::s3::response::{ + DeleteBucketTaggingResponse, GetBucketTaggingResponse, PutBucketTaggingResponse, +}; use minio::s3::types::S3Api; use minio_common::example::create_tags_example; use minio_common::test_context::TestContext; @@ -31,9 +33,9 @@ async fn bucket_tags_s3() { let tags = create_tags_example(); - let resp: SetBucketTagsResponse = ctx + let resp: PutBucketTaggingResponse = ctx .client - .set_bucket_tags(&bucket_name) + .put_bucket_tagging(&bucket_name) .tags(tags.clone()) .send() .await @@ -41,9 +43,9 @@ async fn bucket_tags_s3() { assert_eq!(resp.bucket, bucket_name); assert_eq!(resp.region, DEFAULT_REGION); - let resp: GetBucketTagsResponse = ctx + let resp: GetBucketTaggingResponse = ctx .client - .get_bucket_tags(&bucket_name) + .get_bucket_tagging(&bucket_name) .send() .await .unwrap(); @@ -51,18 +53,18 @@ async fn bucket_tags_s3() { assert_eq!(resp.bucket, bucket_name); assert_eq!(resp.region, DEFAULT_REGION); - let resp: DeleteBucketTagsResponse = ctx + let resp: DeleteBucketTaggingResponse = ctx .client - .delete_bucket_tags(&bucket_name) + .delete_bucket_tagging(&bucket_name) .send() .await .unwrap(); assert_eq!(resp.bucket, bucket_name); assert_eq!(resp.region, DEFAULT_REGION); - let resp: GetBucketTagsResponse = ctx + let resp: GetBucketTaggingResponse = ctx .client - .get_bucket_tags(&bucket_name) + .get_bucket_tagging(&bucket_name) .send() .await .unwrap(); @@ -82,9 +84,9 @@ async fn bucket_tags_s3express() { let tags = create_tags_example(); - let resp: Result = ctx + let resp: Result = ctx .client - .set_bucket_tags(&bucket_name) + .put_bucket_tagging(&bucket_name) .tags(tags.clone()) .send() .await; @@ -93,15 +95,15 @@ async fn bucket_tags_s3express() { v => panic!("Expected error S3Error(NotSupported): but got {:?}", v), } - let resp: Result = - ctx.client.get_bucket_tags(&bucket_name).send().await; + let resp: Result = + ctx.client.get_bucket_tagging(&bucket_name).send().await; match resp { Err(Error::S3Error(e)) => assert_eq!(e.code, ErrorCode::NotSupported), v => panic!("Expected error S3Error(NotSupported): but got {:?}", v), } - let resp: Result = - ctx.client.delete_bucket_tags(&bucket_name).send().await; + let resp: Result = + ctx.client.delete_bucket_tagging(&bucket_name).send().await; match resp { Err(Error::S3Error(e)) => assert_eq!(e.code, ErrorCode::NotSupported), v => panic!("Expected error S3Error(NotSupported): but got {:?}", v), diff --git a/tests/test_bucket_versioning.rs b/tests/test_bucket_versioning.rs index 05d0f71..12251a0 100644 --- a/tests/test_bucket_versioning.rs +++ b/tests/test_bucket_versioning.rs @@ -16,7 +16,7 @@ use minio::s3::builders::VersioningStatus; use minio::s3::client::DEFAULT_REGION; use minio::s3::error::{Error, ErrorCode}; -use minio::s3::response::{GetBucketVersioningResponse, SetBucketVersioningResponse}; +use minio::s3::response::{GetBucketVersioningResponse, PutBucketVersioningResponse}; use minio::s3::types::S3Api; use minio_common::test_context::TestContext; @@ -29,9 +29,9 @@ async fn bucket_versioning_s3() { } let (bucket_name, _cleanup) = ctx.create_bucket_helper().await; - let resp: SetBucketVersioningResponse = ctx + let resp: PutBucketVersioningResponse = ctx .client - .set_bucket_versioning(&bucket_name) + .put_bucket_versioning(&bucket_name) .versioning_status(VersioningStatus::Enabled) .send() .await @@ -49,9 +49,9 @@ async fn bucket_versioning_s3() { assert_eq!(resp.bucket, bucket_name); assert_eq!(resp.region, DEFAULT_REGION); - let resp: SetBucketVersioningResponse = ctx + let resp: PutBucketVersioningResponse = ctx .client - .set_bucket_versioning(&bucket_name) + .put_bucket_versioning(&bucket_name) .versioning_status(VersioningStatus::Suspended) .send() .await @@ -79,9 +79,9 @@ async fn bucket_versioning_s3express() { } let (bucket_name, _cleanup) = ctx.create_bucket_helper().await; - let resp: Result = ctx + let resp: Result = ctx .client - .set_bucket_versioning(&bucket_name) + .put_bucket_versioning(&bucket_name) .versioning_status(VersioningStatus::Enabled) .send() .await; diff --git a/tests/test_list_objects.rs b/tests/test_list_objects.rs index 232d6df..a470b23 100644 --- a/tests/test_list_objects.rs +++ b/tests/test_list_objects.rs @@ -20,8 +20,21 @@ use minio_common::utils::rand_object_name; use std::collections::HashSet; use tokio_stream::StreamExt; -async fn list_objects(use_api_v1: bool, include_versions: bool, unsorted: bool, express: bool) { - const N_OBJECTS: usize = 100; +async fn list_objects( + use_api_v1: bool, + include_versions: bool, + express: bool, + n_prefixes: usize, + n_objects: usize, +) { + if express { + if use_api_v1 { + panic!("S3-Express does not support V1 API"); + } + if include_versions { + panic!("S3-Express does not support versioning"); + } + } let ctx = TestContext::new_from_env(); let is_express = ctx.client.is_minio_express(); @@ -36,27 +49,29 @@ async fn list_objects(use_api_v1: bool, include_versions: bool, unsorted: bool, let (bucket_name, _cleanup) = ctx.create_bucket_helper().await; let mut names_set_before: HashSet = HashSet::new(); - let mut names_vec_after: Vec = Vec::with_capacity(N_OBJECTS); + let mut names_vec_after: Vec = Vec::with_capacity(n_prefixes * n_objects); - for _ in 1..=N_OBJECTS { - let object_name: String = rand_object_name(); - let resp: PutObjectContentResponse = ctx - .client - .put_object_content(&bucket_name, &object_name, "hello world") - .send() - .await - .unwrap(); - assert_eq!(resp.bucket, bucket_name); - assert_eq!(resp.object, object_name); - names_set_before.insert(object_name); + for _ in 0..n_prefixes { + let prefix: String = rand_object_name(); + for _ in 0..=n_objects { + let object_name: String = format!("{}/{}", prefix, rand_object_name()); + let resp: PutObjectContentResponse = ctx + .client + .put_object_content(&bucket_name, &object_name, "hello world") + .send() + .await + .unwrap(); + assert_eq!(resp.bucket, bucket_name); + assert_eq!(resp.object, object_name); + names_set_before.insert(object_name); + } } - let mut stream = ctx .client .list_objects(&bucket_name) .use_api_v1(use_api_v1) .include_versions(include_versions) - .unsorted(unsorted) + .recursive(true) .to_stream() .await; @@ -69,17 +84,13 @@ async fn list_objects(use_api_v1: bool, include_versions: bool, unsorted: bool, assert_eq!(names_vec_after.len(), names_set_before.len()); let is_sorted: bool = names_vec_after.iter().is_sorted(); - if unsorted { - // we expect the results to be unsorted - assert!( - !is_sorted, - "expected the results to be unsorted, yet the list of objects is sorted" - ); + if express { + // we do not expect the results to be sorted, but it still might be } else { // we expect the results to be sorted assert!( is_sorted, - "expected the results to be sorted, yet the list of objects is unsorted" + "With regular (non S3-Express) we expected the results to be sorted, yet the list of objects is unsorted" ); } let names_set_after: HashSet = names_vec_after.into_iter().collect(); @@ -87,26 +98,28 @@ async fn list_objects(use_api_v1: bool, include_versions: bool, unsorted: bool, } #[tokio::test(flavor = "multi_thread", worker_threads = 10)] -async fn list_objects_v1_no_versions_sorted() { - list_objects(true, false, false, false).await; +async fn list_objects_v1_no_versions() { + list_objects(true, false, false, 5, 5).await; } #[tokio::test(flavor = "multi_thread", worker_threads = 10)] -async fn list_objects_v1_with_versions_sorted() { - list_objects(true, true, false, false).await; +async fn list_objects_v1_with_versions() { + list_objects(true, true, false, 5, 5).await; } #[tokio::test(flavor = "multi_thread", worker_threads = 10)] -async fn list_objects_v2_no_versions_sorted() { - list_objects(false, false, false, false).await; +async fn list_objects_v2_no_versions() { + list_objects(false, false, false, 5, 5).await; } #[tokio::test(flavor = "multi_thread", worker_threads = 10)] -async fn list_objects_v2_with_versions_sorted() { - list_objects(false, true, false, false).await; +async fn list_objects_v2_with_versions() { + list_objects(false, true, false, 5, 5).await; } -//#[tokio::test(flavor = "multi_thread", worker_threads = 10)] -async fn list_objects_v2_no_versions_unsorted() { - list_objects(false, false, true, true).await; +/// Test for S3-Express: List objects with S3-Express are only supported with V2 API, without +/// versions, and yield unsorted results. +#[tokio::test(flavor = "multi_thread", worker_threads = 10)] +async fn list_objects_express() { + list_objects(false, false, true, 5, 5).await; } diff --git a/tests/test_listen_bucket_notification.rs b/tests/test_listen_bucket_notification.rs index b948cc0..3d6c864 100644 --- a/tests/test_listen_bucket_notification.rs +++ b/tests/test_listen_bucket_notification.rs @@ -45,7 +45,7 @@ async fn listen_bucket_notification() { let (_resp, mut event_stream) = ctx2 .client - .listen_bucket_notification(&bucket_name2) + .list_bucket_notification(&bucket_name2) .send() .await .unwrap(); diff --git a/tests/test_object_legal_hold.rs b/tests/test_object_legal_hold.rs index 6119abd..d0b75c7 100644 --- a/tests/test_object_legal_hold.rs +++ b/tests/test_object_legal_hold.rs @@ -17,8 +17,8 @@ use bytes::Bytes; use minio::s3::client::DEFAULT_REGION; use minio::s3::response::{ - DisableObjectLegalHoldResponse, EnableObjectLegalHoldResponse, - IsObjectLegalHoldEnabledResponse, MakeBucketResponse, PutObjectContentResponse, + CreateBucketResponse, GetObjectLegalHoldResponse, PutObjectContentResponse, + PutObjectLegalHoldResponse, }; use minio::s3::types::S3Api; use minio_common::cleanup_guard::CleanupGuard; @@ -33,9 +33,9 @@ async fn object_legal_hold_s3() { return; } let bucket_name: String = rand_bucket_name(); - let _resp: MakeBucketResponse = ctx + let _resp: CreateBucketResponse = ctx .client - .make_bucket(&bucket_name) + .create_bucket(&bucket_name) .object_lock(true) .send() .await @@ -53,52 +53,47 @@ async fn object_legal_hold_s3() { assert_eq!(resp.bucket, bucket_name); assert_eq!(resp.object, object_name); assert_eq!(resp.object_size, data.len() as u64); - //println!("response of put object content: resp={:?}", resp); - let resp: DisableObjectLegalHoldResponse = ctx + let resp: PutObjectLegalHoldResponse = ctx .client - .disable_object_legal_hold(&bucket_name, &object_name) + .put_object_legal_hold(&bucket_name, &object_name, true) .send() .await .unwrap(); - //println!("response of setting object legal hold: resp={:?}", resp); assert_eq!(resp.object, object_name); assert_eq!(resp.bucket, bucket_name); assert_eq!(resp.region, DEFAULT_REGION); assert_eq!(resp.version_id, None); - let resp: IsObjectLegalHoldEnabledResponse = ctx + let resp: GetObjectLegalHoldResponse = ctx .client - .is_object_legal_hold_enabled(&bucket_name, &object_name) + .get_object_legal_hold(&bucket_name, &object_name) .send() .await .unwrap(); - //println!("response of getting object legal hold: resp={:?}", resp); - assert!(!resp.enabled); + assert!(resp.enabled); assert_eq!(resp.object, object_name); assert_eq!(resp.bucket, bucket_name); assert_eq!(resp.region, DEFAULT_REGION); assert_eq!(resp.version_id, None); - let resp: EnableObjectLegalHoldResponse = ctx + let resp: PutObjectLegalHoldResponse = ctx .client - .enable_object_legal_hold(&bucket_name, &object_name) + .put_object_legal_hold(&bucket_name, &object_name, true) .send() .await .unwrap(); - //println!("response of setting object legal hold: resp={:?}", resp); assert_eq!(resp.object, object_name); assert_eq!(resp.bucket, bucket_name); assert_eq!(resp.region, DEFAULT_REGION); assert_eq!(resp.version_id, None); - let resp: IsObjectLegalHoldEnabledResponse = ctx + let resp: GetObjectLegalHoldResponse = ctx .client - .is_object_legal_hold_enabled(&bucket_name, &object_name) + .get_object_legal_hold(&bucket_name, &object_name) .send() .await .unwrap(); - //println!("response of getting object legal hold: resp={:?}", resp); assert!(resp.enabled); assert_eq!(resp.object, object_name); assert_eq!(resp.bucket, bucket_name); diff --git a/tests/test_object_lock_config.rs b/tests/test_object_lock_config.rs index 2738baf..1725a51 100644 --- a/tests/test_object_lock_config.rs +++ b/tests/test_object_lock_config.rs @@ -15,7 +15,7 @@ use minio::s3::client::DEFAULT_REGION; use minio::s3::response::{ - DeleteObjectLockConfigResponse, GetObjectLockConfigResponse, SetObjectLockConfigResponse, + DeleteObjectLockConfigResponse, GetObjectLockConfigResponse, PutObjectLockConfigResponse, }; use minio::s3::types::{ObjectLockConfig, RetentionMode, S3Api}; use minio_common::cleanup_guard::CleanupGuard; @@ -32,7 +32,7 @@ async fn object_lock_config() { let bucket_name: String = rand_bucket_name(); ctx.client - .make_bucket(&bucket_name) + .create_bucket(&bucket_name) .object_lock(true) .send() .await @@ -43,9 +43,9 @@ async fn object_lock_config() { let config = ObjectLockConfig::new(RetentionMode::GOVERNANCE, Some(DURATION_DAYS), None).unwrap(); - let resp: SetObjectLockConfigResponse = ctx + let resp: PutObjectLockConfigResponse = ctx .client - .set_object_lock_config(&bucket_name) + .put_object_lock_config(&bucket_name) .config(config) .send() .await diff --git a/tests/test_object_retention.rs b/tests/test_object_retention.rs index 02f249f..cc55101 100644 --- a/tests/test_object_retention.rs +++ b/tests/test_object_retention.rs @@ -16,8 +16,8 @@ use minio::s3::builders::ObjectContent; use minio::s3::client::DEFAULT_REGION; use minio::s3::response::{ - GetObjectRetentionResponse, MakeBucketResponse, PutObjectContentResponse, - SetObjectRetentionResponse, + CreateBucketResponse, GetObjectRetentionResponse, PutObjectContentResponse, + PutObjectRetentionResponse, }; use minio::s3::types::{RetentionMode, S3Api}; use minio::s3::utils::{to_iso8601utc, utc_now}; @@ -35,9 +35,9 @@ async fn object_retention() { } let bucket_name: String = rand_bucket_name(); - let resp: MakeBucketResponse = ctx + let resp: CreateBucketResponse = ctx .client - .make_bucket(&bucket_name) + .create_bucket(&bucket_name) .object_lock(true) .send() .await @@ -66,9 +66,9 @@ async fn object_retention() { //assert_eq!(resp.etag, ""); let retain_until_date = utc_now() + chrono::Duration::days(1); - let obj_resp: SetObjectRetentionResponse = ctx + let obj_resp: PutObjectRetentionResponse = ctx .client - .set_object_retention(&bucket_name, &object_name) + .put_object_retention(&bucket_name, &object_name) .retention_mode(Some(RetentionMode::GOVERNANCE)) .retain_until_date(Some(retain_until_date)) .send() @@ -91,9 +91,9 @@ async fn object_retention() { to_iso8601utc(retain_until_date) ); - let resp: SetObjectRetentionResponse = ctx + let resp: PutObjectRetentionResponse = ctx .client - .set_object_retention(&bucket_name, &object_name) + .put_object_retention(&bucket_name, &object_name) .bypass_governance_mode(true) .send() .await diff --git a/tests/test_object_tags.rs b/tests/test_object_tags.rs index f0c313c..70a5f89 100644 --- a/tests/test_object_tags.rs +++ b/tests/test_object_tags.rs @@ -16,8 +16,8 @@ use minio::s3::builders::ObjectContent; use minio::s3::client::DEFAULT_REGION; use minio::s3::response::{ - DeleteObjectTagsResponse, GetObjectTagsResponse, PutObjectContentResponse, - SetObjectTagsResponse, + DeleteObjectTaggingResponse, GetObjectTaggingResponse, PutObjectContentResponse, + PutObjectTaggingResponse, }; use minio::s3::types::S3Api; use minio_common::rand_src::RandSrc; @@ -58,9 +58,9 @@ async fn object_tags() { (String::from("User"), String::from("jsmith")), ]); - let resp: SetObjectTagsResponse = ctx + let resp: PutObjectTaggingResponse = ctx .client - .set_object_tags(&bucket_name, &object_name) + .put_object_tagging(&bucket_name, &object_name) .tags(tags.clone()) .send() .await @@ -70,9 +70,9 @@ async fn object_tags() { assert_eq!(resp.version_id, None); assert_eq!(resp.region, DEFAULT_REGION); - let resp: GetObjectTagsResponse = ctx + let resp: GetObjectTaggingResponse = ctx .client - .get_object_tags(&bucket_name, &object_name) + .get_object_tagging(&bucket_name, &object_name) .send() .await .unwrap(); @@ -82,9 +82,9 @@ async fn object_tags() { assert_eq!(resp.version_id, None); assert_eq!(resp.region, DEFAULT_REGION); - let resp: DeleteObjectTagsResponse = ctx + let resp: DeleteObjectTaggingResponse = ctx .client - .delete_object_tags(&bucket_name, &object_name) + .delete_object_tagging(&bucket_name, &object_name) .send() .await .unwrap(); @@ -93,9 +93,9 @@ async fn object_tags() { assert_eq!(resp.version_id, None); assert_eq!(resp.region, DEFAULT_REGION); - let resp: GetObjectTagsResponse = ctx + let resp: GetObjectTaggingResponse = ctx .client - .get_object_tags(&bucket_name, &object_name) + .get_object_tagging(&bucket_name, &object_name) .send() .await .unwrap();