pub mod bucket;
pub mod file;
use crate::core::middleware::AuthMiddleware;
use bucket::Bucket;
use reqwest::Client;
use reqwest_middleware::{ClientBuilder, ClientWithMiddleware};
use reqwest_retry::{policies::ExponentialBackoff, RetryTransientMiddleware};
use thiserror::Error;
const STORAGE_V1_API: &str = "https://storage.googleapis.com/storage/v1";
#[derive(Error, Debug)]
pub enum StorageError {
#[error("HTTP Request failed: {0}")]
RequestError(#[from] reqwest::Error),
#[error("Middleware error: {0}")]
MiddlewareError(#[from] reqwest_middleware::Error),
#[error("API error: {0}")]
ApiError(String),
#[error("Serialization error: {0}")]
SerializationError(#[from] serde_json::Error),
#[error("Project ID is missing in service account key")]
ProjectIdMissing,
}
#[derive(Clone)]
pub struct FirebaseStorage {
client: ClientWithMiddleware,
pub base_url: String,
pub project_id: String,
middleware: AuthMiddleware,
}
impl FirebaseStorage {
pub fn new(middleware: AuthMiddleware) -> Self {
let retry_policy = ExponentialBackoff::builder().build_with_max_retries(3);
let client = ClientBuilder::new(Client::new())
.with(RetryTransientMiddleware::new_with_policy(retry_policy))
.with(middleware.clone())
.build();
let project_id = middleware.key.project_id.clone().unwrap_or_default();
let base_url = STORAGE_V1_API.to_string();
Self {
client,
base_url,
project_id,
middleware,
}
}
#[cfg(test)]
pub(crate) fn new_with_client(client: ClientWithMiddleware, base_url: String, middleware: AuthMiddleware) -> Self {
let project_id = middleware.key.project_id.clone().unwrap_or_default();
Self {
client,
base_url,
project_id,
middleware,
}
}
pub fn bucket(&self, name: Option<&str>) -> Bucket {
let bucket_name = match name {
Some(n) => n.to_string(),
None => format!("{}.appspot.com", self.project_id),
};
Bucket::new(self.client.clone(), self.base_url.clone(), bucket_name, self.middleware.clone())
}
}
#[cfg(test)]
mod tests;