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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,11 +1,26 @@
// MinIO Rust Library for Amazon S3 Compatible Cloud Storage
// Copyright 2025 MinIO, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use minio::s3::creds::StaticProvider;
use minio::s3::http::BaseUrl;
use minio::s3::response::BucketExistsResponse;
use minio::s3::types::S3Api;
use minio::s3::{Client, ClientBuilder};
use minio::s3::{MinioClient, MinioClientBuilder};
#[allow(dead_code)]
pub fn create_client_on_play() -> Result<Client, Box<dyn std::error::Error + Send + Sync>> {
pub fn create_client_on_play() -> Result<MinioClient, Box<dyn std::error::Error + Send + Sync>> {
let base_url = "https://play.min.io".parse::<BaseUrl>()?;
log::info!("Trying to connect to MinIO at: `{base_url:?}`");
@ -15,20 +30,7 @@ pub fn create_client_on_play() -> Result<Client, Box<dyn std::error::Error + Sen
None,
);
let client = ClientBuilder::new(base_url.clone())
.provider(Some(static_provider))
.build()?;
Ok(client)
}
#[allow(dead_code)]
pub fn create_client_on_localhost() -> Result<Client, Box<dyn std::error::Error + Send + Sync>> {
let base_url = "http://localhost:9000/".parse::<BaseUrl>()?;
log::info!("Trying to connect to MinIO at: `{base_url:?}`");
let static_provider = StaticProvider::new("minioadmin", "minioadmin", None);
let client = ClientBuilder::new(base_url.clone())
let client = MinioClientBuilder::new(base_url.clone())
.provider(Some(static_provider))
.build()?;
Ok(client)
@ -36,14 +38,14 @@ pub fn create_client_on_localhost() -> Result<Client, Box<dyn std::error::Error
pub async fn create_bucket_if_not_exists(
bucket_name: &str,
client: &Client,
client: &MinioClient,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
// Check 'bucket_name' bucket exist or not.
let resp: BucketExistsResponse = client.bucket_exists(bucket_name).send().await?;
let resp: BucketExistsResponse = client.bucket_exists(bucket_name).build().send().await?;
// Make 'bucket_name' bucket if not exist.
if !resp.exists() {
client.create_bucket(bucket_name).send().await.unwrap();
client.create_bucket(bucket_name).build().send().await?;
};
Ok(())
}

View File

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

View File

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

View File

@ -16,8 +16,8 @@
mod common;
use crate::common::create_bucket_if_not_exists;
use minio::s3::MinioClientBuilder;
use minio::s3::builders::ObjectContent;
use minio::s3::client::ClientBuilder;
use minio::s3::creds::StaticProvider;
use minio::s3::http::BaseUrl;
use minio::s3::response::GetObjectPromptResponse;
@ -34,7 +34,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let static_provider = StaticProvider::new("admin", "admin", None);
let client = ClientBuilder::new(base_url.clone())
let client = MinioClientBuilder::new(base_url.clone())
.provider(Some(static_provider))
.ignore_cert_check(Some(true))
.build()?;
@ -58,6 +58,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let content = ObjectContent::from(filename);
client
.put_object_content(bucket_name, object_name, content)
.build()
.send()
.await?;
@ -69,6 +70,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
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
.build()
.send()
.await?;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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