Skip to content

Commit

Permalink
Add builders for bucket methods: (#76)
Browse files Browse the repository at this point in the history
- list buckets
- get bucket versioning
  • Loading branch information
donatello authored Apr 3, 2024
1 parent 6a34d4c commit 35954da
Show file tree
Hide file tree
Showing 7 changed files with 236 additions and 134 deletions.
24 changes: 0 additions & 24 deletions src/s3/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,27 +301,6 @@ impl<'a> MakeBucketArgs<'a> {
}
}

#[derive(Clone, Debug, Default)]
/// Argument for [list_buckets()](crate::s3::client::Client::list_buckets) API
pub struct ListBucketsArgs<'a> {
pub extra_headers: Option<&'a Multimap>,
pub extra_query_params: Option<&'a Multimap>,
}

impl<'a> ListBucketsArgs<'a> {
/// Returns argument for [list_buckets()](crate::s3::client::Client::list_buckets) API
///
/// # Examples
///
/// ```
/// use minio::s3::args::*;
/// let args = ListBucketsArgs::new();
/// ```
pub fn new() -> ListBucketsArgs<'a> {
ListBucketsArgs::default()
}
}

#[derive(Clone, Debug, Default)]
/// Argument for [abort_multipart_upload()](crate::s3::client::Client::abort_multipart_upload) API
pub struct AbortMultipartUploadArgs<'a> {
Expand Down Expand Up @@ -1767,9 +1746,6 @@ impl<'a> SetBucketTagsArgs<'a> {
}
}

/// Argument for [get_bucket_versioning()](crate::s3::client::Client::get_bucket_versioning) API
pub type GetBucketVersioningArgs<'a> = BucketArgs<'a>;

/// Argument for [set_bucket_versioning()](crate::s3::client::Client::set_bucket_versioning) API
pub struct SetBucketVersioningArgs<'a> {
pub extra_headers: Option<&'a Multimap>,
Expand Down
2 changes: 2 additions & 0 deletions src/s3/builders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@

//! Argument builders for [minio::s3::client::Client](crate::s3::client::Client) APIs
mod buckets;
mod list_objects;
mod listen_bucket_notification;

pub use buckets::*;
pub use list_objects::*;
pub use listen_bucket_notification::*;
140 changes: 140 additions & 0 deletions src/s3/builders/buckets.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
use http::Method;

use crate::s3::{
client::Client,
error::Error,
response::{GetBucketVersioningResponse, ListBucketsResponse},
types::{S3Api, S3Request, ToS3Request},
utils::{check_bucket_name, merge, Multimap},
};

/// Argument builder for
/// [list_buckets()](crate::s3::client::Client::list_buckets) API.
#[derive(Clone, Debug, Default)]
pub struct ListBuckets {
client: Option<Client>,

extra_headers: Option<Multimap>,
extra_query_params: Option<Multimap>,
}

impl S3Api for ListBuckets {
type S3Response = ListBucketsResponse;
}

impl ToS3Request for ListBuckets {
fn to_s3request(&self) -> Result<S3Request, Error> {
let mut headers = Multimap::new();
if let Some(v) = &self.extra_headers {
headers = v.clone();
}
let mut query_params = Multimap::new();
if let Some(v) = &self.extra_query_params {
query_params = v.clone();
}

let req = S3Request::new(
self.client.as_ref().ok_or(Error::NoClientProvided)?,
Method::GET,
)
.query_params(query_params)
.headers(headers);
Ok(req)
}
}

impl ListBuckets {
pub fn new() -> Self {
Default::default()
}

pub fn client(mut self, client: &Client) -> Self {
self.client = Some(client.clone());
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
}
}

#[derive(Clone, Debug, Default)]
pub struct BucketCommon {
client: Option<Client>,

extra_headers: Option<Multimap>,
extra_query_params: Option<Multimap>,
region: Option<String>,
bucket: String,
}

impl BucketCommon {
pub fn new(bucket_name: &str) -> Self {
BucketCommon {
bucket: bucket_name.to_owned(),
..Default::default()
}
}

pub fn client(mut self, client: &Client) -> Self {
self.client = Some(client.clone());
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 region(mut self, region: Option<String>) -> Self {
self.region = region;
self
}
}

/// Argument builder for
/// [get_bucket_versioning()](crate::s3::client::Client::get_bucket_versioning)
/// API
pub type GetBucketVersioning = BucketCommon;

impl S3Api for GetBucketVersioning {
type S3Response = GetBucketVersioningResponse;
}

impl ToS3Request for GetBucketVersioning {
fn to_s3request(&self) -> Result<S3Request, Error> {
check_bucket_name(&self.bucket, true)?;

let mut headers = Multimap::new();
if let Some(v) = &self.extra_headers {
merge(&mut headers, v);
}

let mut query_params = Multimap::new();
if let Some(v) = &self.extra_query_params {
merge(&mut query_params, v);
}
query_params.insert(String::from("versioning"), String::new());

let req = S3Request::new(
self.client.as_ref().ok_or(Error::NoClientProvided)?,
Method::GET,
)
.region(self.region.as_deref())
.bucket(Some(&self.bucket))
.query_params(query_params)
.headers(headers);
Ok(req)
}
}
91 changes: 7 additions & 84 deletions src/s3/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use crate::s3::response::*;
use crate::s3::signer::{presign_v4, sign_v4_s3};
use crate::s3::sse::SseCustomerKey;
use crate::s3::types::{
Bucket, DeleteObject, Directive, LifecycleConfig, NotificationConfig, ObjectLockConfig, Part,
DeleteObject, Directive, LifecycleConfig, NotificationConfig, ObjectLockConfig, Part,
ReplicationConfig, RetentionMode, SseConfig,
};
use crate::s3::utils::{
Expand All @@ -46,6 +46,8 @@ use xmltree::Element;
mod list_objects;
mod listen_bucket_notification;

use super::builders::{GetBucketVersioning, ListBuckets};

/// Client Builder manufactures a Client using given parameters.
#[derive(Debug, Default)]
pub struct ClientBuilder {
Expand Down Expand Up @@ -1846,46 +1848,8 @@ impl Client {
}
}

pub async fn get_bucket_versioning(
&self,
args: &GetBucketVersioningArgs<'_>,
) -> Result<GetBucketVersioningResponse, Error> {
let region = self.get_region(args.bucket, args.region).await?;

let mut headers = Multimap::new();
if let Some(v) = &args.extra_headers {
merge(&mut headers, v);
}

let mut query_params = Multimap::new();
if let Some(v) = &args.extra_query_params {
merge(&mut query_params, v);
}
query_params.insert(String::from("versioning"), String::new());

let resp = self
.execute(
Method::GET,
&region,
&mut headers,
&query_params,
Some(args.bucket),
None,
None,
)
.await?;

let header_map = resp.headers().clone();
let body = resp.bytes().await?;
let root = Element::parse(body.reader())?;

Ok(GetBucketVersioningResponse {
headers: header_map.clone(),
region: region.clone(),
bucket_name: args.bucket.to_string(),
status: get_option_text(&root, "Status").map(|v| v == "Enabled"),
mfa_delete: get_option_text(&root, "MFADelete").map(|v| v == "Enabled"),
})
pub fn get_bucket_versioning(&self, bucket: &str) -> GetBucketVersioning {
GetBucketVersioning::new(bucket).client(self)
}

pub async fn get_object(&self, args: &GetObjectArgs<'_>) -> Result<reqwest::Response, Error> {
Expand Down Expand Up @@ -2230,49 +2194,8 @@ impl Client {
}
}

pub async fn list_buckets(
&self,
args: &ListBucketsArgs<'_>,
) -> Result<ListBucketsResponse, Error> {
let mut headers = Multimap::new();
if let Some(v) = &args.extra_headers {
merge(&mut headers, v);
}
let mut query_params = &Multimap::new();
if let Some(v) = &args.extra_query_params {
query_params = v;
}
let resp = self
.execute(
Method::GET,
&String::from("us-east-1"),
&mut headers,
query_params,
None,
None,
None,
)
.await?;
let header_map = resp.headers().clone();
let body = resp.bytes().await?;
let mut root = Element::parse(body.reader())?;
let buckets = root
.get_mut_child("Buckets")
.ok_or(Error::XmlError(String::from("<Buckets> tag not found")))?;

let mut bucket_list: Vec<Bucket> = Vec::new();
while let Some(b) = buckets.take_child("Bucket") {
let bucket = b;
bucket_list.push(Bucket {
name: get_text(&bucket, "Name")?,
creation_date: from_iso8601utc(&get_text(&bucket, "CreationDate")?)?,
})
}

Ok(ListBucketsResponse {
headers: header_map.clone(),
buckets: bucket_list,
})
pub fn list_buckets(&self) -> ListBuckets {
ListBuckets::new().client(self)
}

pub async fn make_bucket(
Expand Down
23 changes: 4 additions & 19 deletions src/s3/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,28 +24,23 @@ use xmltree::Element;

use crate::s3::error::Error;
use crate::s3::types::{
parse_legal_hold, Bucket, LifecycleConfig, NotificationConfig, ObjectLockConfig,
ReplicationConfig, RetentionMode, SelectProgress, SseConfig,
parse_legal_hold, LifecycleConfig, NotificationConfig, ObjectLockConfig, ReplicationConfig,
RetentionMode, SelectProgress, SseConfig,
};
use crate::s3::utils::{
copy_slice, crc32, from_http_header_value, from_iso8601utc, get_text, uint32, UtcTime,
};

mod buckets;
mod list_objects;
mod listen_bucket_notification;

pub use buckets::{GetBucketVersioningResponse, ListBucketsResponse};
pub use list_objects::{
ListObjectVersionsResponse, ListObjectsResponse, ListObjectsV1Response, ListObjectsV2Response,
};
pub use listen_bucket_notification::ListenBucketNotificationResponse;

#[derive(Debug)]
/// Response of [list_buckets()](crate::s3::client::Client::list_buckets) API
pub struct ListBucketsResponse {
pub headers: HeaderMap,
pub buckets: Vec<Bucket>,
}

#[derive(Debug)]
/// Base response for bucket operation
pub struct BucketResponse {
Expand Down Expand Up @@ -675,16 +670,6 @@ pub struct GetBucketTagsResponse {
/// Response of [set_bucket_tags()](crate::s3::client::Client::set_bucket_tags) API
pub type SetBucketTagsResponse = BucketResponse;

#[derive(Clone, Debug)]
/// Response of [get_bucket_versioning()](crate::s3::client::Client::get_bucket_versioning) API
pub struct GetBucketVersioningResponse {
pub headers: HeaderMap,
pub region: String,
pub bucket_name: String,
pub status: Option<bool>,
pub mfa_delete: Option<bool>,
}

/// Response of [set_bucket_versioning()](crate::s3::client::Client::set_bucket_versioning) API
pub type SetBucketVersioningResponse = BucketResponse;

Expand Down
Loading

0 comments on commit 35954da

Please sign in to comment.