s3/bucket/
mod.rs

1mod presign;
2use crate::error::S3Error;
3use awscreds::Credentials;
4use awsregion::Region;
5use http::HeaderMap;
6use std::collections::HashMap;
7use std::sync::{Arc, RwLock};
8use std::time::Duration;
9
10pub use std::io::Read;
11
12pub use presign::*;
13
14mod credentials;
15pub use credentials::*;
16
17mod tag;
18pub use tag::*;
19
20mod create;
21pub use create::*;
22
23mod list;
24pub use list::*;
25
26mod delete;
27pub use delete::*;
28
29mod copy;
30pub use copy::*;
31
32mod get;
33pub use get::*;
34
35mod put;
36pub use put::*;
37
38mod head;
39pub use head::*;
40
41mod utils;
42pub use utils::*;
43
44pub type Query = HashMap<String, String>;
45
46pub use crate::serde_types::{
47    BucketLocationResult, CompleteMultipartUploadData, CorsConfiguration, HeadObjectResult,
48    InitiateMultipartUploadResponse, ListBucketResult, ListMultipartUploadsResult, Part,
49};
50pub(crate) use crate::utils::error_from_response_data;
51pub use crate::utils::PutStreamResponse;
52
53pub use crate::request::Request;
54
55pub const CHUNK_SIZE: usize = 8_388_608; // 8 Mebibytes, min is 5 (5_242_880);
56
57/// Instantiate an existing Bucket
58///
59/// # Example
60///
61/// ```no_run
62/// use s3::bucket::Bucket;
63/// use s3::creds::Credentials;
64///
65/// let bucket_name = "rust-s3-test";
66/// let region = "us-east-1".parse().unwrap();
67/// let credentials = Credentials::default().unwrap();
68///
69/// let bucket = Bucket::new(bucket_name, region, credentials);
70/// ```
71#[derive(Clone, Debug)]
72pub struct Bucket {
73    pub name: String,
74    pub region: Region,
75    pub credentials: Arc<RwLock<Credentials>>,
76    pub extra_headers: HeaderMap,
77    pub extra_query: Query,
78    pub request_timeout: Option<Duration>,
79    path_style: bool,
80    listobjects_v2: bool,
81}
82
83const DEFAULT_REQUEST_TIMEOUT: Option<Duration> = Some(Duration::from_secs(60));
84
85fn validate_expiry(expiry_secs: u32) -> Result<(), S3Error> {
86    if 604800 < expiry_secs {
87        return Err(S3Error::MaxExpiry(expiry_secs));
88    }
89    Ok(())
90}
91
92impl Bucket {
93    pub fn with_path_style(&self) -> Self {
94        Self {
95            name: self.name.clone(),
96            region: self.region.clone(),
97            credentials: self.credentials.clone(),
98            extra_headers: self.extra_headers.clone(),
99            extra_query: self.extra_query.clone(),
100            request_timeout: self.request_timeout,
101            path_style: true,
102            listobjects_v2: self.listobjects_v2,
103        }
104    }
105
106    pub fn with_extra_headers(&self, extra_headers: HeaderMap) -> Self {
107        Self {
108            name: self.name.clone(),
109            region: self.region.clone(),
110            credentials: self.credentials.clone(),
111            extra_headers,
112            extra_query: self.extra_query.clone(),
113            request_timeout: self.request_timeout,
114            path_style: self.path_style,
115            listobjects_v2: self.listobjects_v2,
116        }
117    }
118
119    pub fn with_extra_query(&self, extra_query: HashMap<String, String>) -> Self {
120        Self {
121            name: self.name.clone(),
122            region: self.region.clone(),
123            credentials: self.credentials.clone(),
124            extra_headers: self.extra_headers.clone(),
125            extra_query,
126            request_timeout: self.request_timeout,
127            path_style: self.path_style,
128            listobjects_v2: self.listobjects_v2,
129        }
130    }
131
132    pub fn with_request_timeout(&self, request_timeout: Duration) -> Self {
133        Self {
134            name: self.name.clone(),
135            region: self.region.clone(),
136            credentials: self.credentials.clone(),
137            extra_headers: self.extra_headers.clone(),
138            extra_query: self.extra_query.clone(),
139            request_timeout: Some(request_timeout),
140            path_style: self.path_style,
141            listobjects_v2: self.listobjects_v2,
142        }
143    }
144
145    pub fn with_listobjects_v1(&self) -> Self {
146        Self {
147            name: self.name.clone(),
148            region: self.region.clone(),
149            credentials: self.credentials.clone(),
150            extra_headers: self.extra_headers.clone(),
151            extra_query: self.extra_query.clone(),
152            request_timeout: self.request_timeout,
153            path_style: self.path_style,
154            listobjects_v2: false,
155        }
156    }
157
158    pub(crate) fn _tags_xml<S: AsRef<str>>(&self, tags: &[(S, S)]) -> String {
159        let mut s = String::new();
160        let content = tags
161            .iter()
162            .map(|(name, value)| {
163                format!(
164                    "<Tag><Key>{}</Key><Value>{}</Value></Tag>",
165                    name.as_ref(),
166                    value.as_ref()
167                )
168            })
169            .fold(String::new(), |mut a, b| {
170                a.push_str(b.as_str());
171                a
172            });
173        s.push_str("<Tagging><TagSet>");
174        s.push_str(&content);
175        s.push_str("</TagSet></Tagging>");
176        s
177    }
178}