mirror of
https://github.com/stalwartlabs/mail-server.git
synced 2024-10-23 15:00:14 +00:00
Support for S3 bucket prefixes
This commit is contained in:
parent
0bd4f8148e
commit
417bc38288
2 changed files with 27 additions and 9 deletions
|
@ -21,7 +21,7 @@
|
|||
* for more details.
|
||||
*/
|
||||
|
||||
use std::{ops::Range, time::Duration};
|
||||
use std::{io::Write, ops::Range, time::Duration};
|
||||
|
||||
use s3::{
|
||||
creds::{error::CredentialsError, Credentials},
|
||||
|
@ -35,6 +35,7 @@ use utils::{
|
|||
|
||||
pub struct S3Store {
|
||||
bucket: Bucket,
|
||||
prefix: Option<String>,
|
||||
}
|
||||
|
||||
impl S3Store {
|
||||
|
@ -67,6 +68,7 @@ impl S3Store {
|
|||
)?
|
||||
.with_path_style()
|
||||
.with_request_timeout(timeout),
|
||||
prefix: config.value((&prefix, "key-prefix")).map(|s| s.to_string()),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -75,7 +77,7 @@ impl S3Store {
|
|||
key: &[u8],
|
||||
range: Range<u32>,
|
||||
) -> crate::Result<Option<Vec<u8>>> {
|
||||
let path = Base32Writer::from_bytes(key).finalize();
|
||||
let path = self.build_key(key);
|
||||
let response = if range.start != 0 || range.end != u32::MAX {
|
||||
self.bucket
|
||||
.get_object_range(
|
||||
|
@ -102,11 +104,7 @@ impl S3Store {
|
|||
}
|
||||
|
||||
pub(crate) async fn put_blob(&self, key: &[u8], data: &[u8]) -> crate::Result<()> {
|
||||
match self
|
||||
.bucket
|
||||
.put_object(Base32Writer::from_bytes(key).finalize(), data)
|
||||
.await
|
||||
{
|
||||
match self.bucket.put_object(self.build_key(key), data).await {
|
||||
Ok(response) if (200..300).contains(&response.status_code()) => Ok(()),
|
||||
Ok(response) => Err(crate::Error::InternalError(format!(
|
||||
"S3 error code {}: {}",
|
||||
|
@ -119,11 +117,23 @@ impl S3Store {
|
|||
|
||||
pub(crate) async fn delete_blob(&self, key: &[u8]) -> crate::Result<bool> {
|
||||
self.bucket
|
||||
.delete_object(Base32Writer::from_bytes(key).finalize())
|
||||
.delete_object(self.build_key(key))
|
||||
.await
|
||||
.map(|response| (200..300).contains(&response.status_code()))
|
||||
.map_err(|e| e.into())
|
||||
}
|
||||
|
||||
fn build_key(&self, key: &[u8]) -> String {
|
||||
if let Some(prefix) = &self.prefix {
|
||||
let mut writer =
|
||||
Base32Writer::with_raw_capacity(prefix.len() + ((key.len() + 3) / 4 * 5));
|
||||
writer.push_string(prefix);
|
||||
writer.write_all(key).unwrap();
|
||||
writer.finalize()
|
||||
} else {
|
||||
Base32Writer::from_bytes(key).finalize()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<S3Error> for crate::Error {
|
||||
|
|
|
@ -57,8 +57,12 @@ impl Base32Writer {
|
|||
}
|
||||
|
||||
pub fn with_capacity(capacity: usize) -> Self {
|
||||
Self::with_raw_capacity((capacity + 3) / 4 * 5)
|
||||
}
|
||||
|
||||
pub fn with_raw_capacity(capacity: usize) -> Self {
|
||||
Base32Writer {
|
||||
result: String::with_capacity((capacity + 3) / 4 * 5),
|
||||
result: String::with_capacity(capacity),
|
||||
last_byte: 0,
|
||||
pos: 0,
|
||||
}
|
||||
|
@ -68,6 +72,10 @@ impl Base32Writer {
|
|||
self.result.push(ch);
|
||||
}
|
||||
|
||||
pub fn push_string(&mut self, string: &str) {
|
||||
self.result.push_str(string);
|
||||
}
|
||||
|
||||
fn push_byte(&mut self, byte: u8, is_remainder: bool) {
|
||||
let (ch1, ch2) = match self.pos % 5 {
|
||||
0 => ((byte & 0xF8) >> 3, u8::MAX),
|
||||
|
|
Loading…
Reference in a new issue