this repo has no description
1use async_trait::async_trait; 2use thiserror::Error; 3use aws_sdk_s3::Client; 4use aws_sdk_s3::primitives::ByteStream; 5use aws_config::meta::region::RegionProviderChain; 6use aws_config::BehaviorVersion; 7 8#[derive(Error, Debug)] 9pub enum StorageError { 10 #[error("IO error: {0}")] 11 Io(#[from] std::io::Error), 12 #[error("S3 error: {0}")] 13 S3(String), 14 #[error("Other: {0}")] 15 Other(String), 16} 17 18#[async_trait] 19pub trait BlobStorage: Send + Sync { 20 async fn put(&self, key: &str, data: &[u8]) -> Result<(), StorageError>; 21 async fn get(&self, key: &str) -> Result<Vec<u8>, StorageError>; 22 async fn delete(&self, key: &str) -> Result<(), StorageError>; 23} 24 25pub struct S3BlobStorage { 26 client: Client, 27 bucket: String, 28} 29 30impl S3BlobStorage { 31 pub async fn new() -> Self { 32 // heheheh 33 let region_provider = RegionProviderChain::default_provider().or_else("us-east-1"); 34 let config = aws_config::defaults(BehaviorVersion::latest()) 35 .region(region_provider) 36 .load() 37 .await; 38 39 let bucket = std::env::var("S3_BUCKET").expect("S3_BUCKET must be set"); 40 41 let client = if let Ok(endpoint) = std::env::var("S3_ENDPOINT") { 42 let s3_config = aws_sdk_s3::config::Builder::from(&config) 43 .endpoint_url(endpoint) 44 .force_path_style(true) 45 .build(); 46 Client::from_conf(s3_config) 47 } else { 48 Client::new(&config) 49 }; 50 51 Self { client, bucket } 52 } 53} 54 55#[async_trait] 56impl BlobStorage for S3BlobStorage { 57 async fn put(&self, key: &str, data: &[u8]) -> Result<(), StorageError> { 58 self.client.put_object() 59 .bucket(&self.bucket) 60 .key(key) 61 .body(ByteStream::from(data.to_vec())) 62 .send() 63 .await 64 .map_err(|e| StorageError::S3(e.to_string()))?; 65 Ok(()) 66 } 67 68 async fn get(&self, key: &str) -> Result<Vec<u8>, StorageError> { 69 let resp = self.client.get_object() 70 .bucket(&self.bucket) 71 .key(key) 72 .send() 73 .await 74 .map_err(|e| StorageError::S3(e.to_string()))?; 75 76 let data = resp.body.collect().await 77 .map_err(|e| StorageError::S3(e.to_string()))? 78 .into_bytes(); 79 80 Ok(data.to_vec()) 81 } 82 83 async fn delete(&self, key: &str) -> Result<(), StorageError> { 84 self.client.delete_object() 85 .bucket(&self.bucket) 86 .key(key) 87 .send() 88 .await 89 .map_err(|e| StorageError::S3(e.to_string()))?; 90 Ok(()) 91 } 92}