feat: add file serving endpoint GET /assets/:id/file
This commit is contained in:
@@ -64,7 +64,7 @@ pub async fn build_app(config: &Config) -> Result<Router> {
|
||||
|
||||
// File storage for ingest
|
||||
let storage_path = std::env::var("STORAGE_PATH").unwrap_or_else(|_| "./data/media".to_string());
|
||||
let file_storage = Arc::new(LocalFileStorage::new(&storage_path));
|
||||
let file_storage: Arc<LocalFileStorage> = Arc::new(LocalFileStorage::new(&storage_path));
|
||||
|
||||
// Album handlers
|
||||
let create_album_handler = Arc::new(CreateAlbumHandler::new(album_repo.clone()));
|
||||
@@ -78,7 +78,7 @@ pub async fn build_app(config: &Config) -> Result<Router> {
|
||||
quota_repo,
|
||||
ledger_repo,
|
||||
asset_repo.clone(),
|
||||
file_storage,
|
||||
file_storage.clone(),
|
||||
event_publisher.clone(),
|
||||
));
|
||||
let get_asset_handler = Arc::new(GetAssetHandler::new(
|
||||
@@ -90,7 +90,7 @@ pub async fn build_app(config: &Config) -> Result<Router> {
|
||||
metadata_repo.clone(),
|
||||
));
|
||||
let update_metadata_handler = Arc::new(UpdateMetadataHandler::new(
|
||||
asset_repo,
|
||||
asset_repo.clone(),
|
||||
metadata_repo,
|
||||
event_publisher,
|
||||
));
|
||||
@@ -115,6 +115,8 @@ pub async fn build_app(config: &Config) -> Result<Router> {
|
||||
update_metadata_handler,
|
||||
register_volume_handler,
|
||||
register_library_path_handler,
|
||||
file_storage,
|
||||
asset_repo,
|
||||
);
|
||||
|
||||
let cors = CorsLayer::new()
|
||||
|
||||
@@ -9,8 +9,10 @@ use application::{
|
||||
};
|
||||
use axum::{
|
||||
Json,
|
||||
body::Body,
|
||||
extract::{Multipart, Path, Query, State},
|
||||
http::StatusCode,
|
||||
http::{StatusCode, header},
|
||||
response::Response,
|
||||
};
|
||||
use domain::value_objects::{MetadataValue, StructuredData, SystemId};
|
||||
use sha2::{Digest, Sha256};
|
||||
@@ -171,3 +173,39 @@ pub async fn update_metadata(
|
||||
state.update_metadata_handler.execute(cmd).await?;
|
||||
Ok(Json(serde_json::json!({ "status": "updated" })))
|
||||
}
|
||||
|
||||
pub async fn serve_file(
|
||||
State(state): State<AppState>,
|
||||
_claims: JwtClaims,
|
||||
Path((asset_id,)): Path<(uuid::Uuid,)>,
|
||||
) -> Result<Response, AppError> {
|
||||
let asset = state
|
||||
.asset_repo
|
||||
.find_by_id(&SystemId::from_uuid(asset_id))
|
||||
.await?
|
||||
.ok_or_else(|| domain::errors::DomainError::NotFound("Asset not found".into()))?;
|
||||
|
||||
let data = state
|
||||
.file_storage
|
||||
.read_file(&asset.source_reference.relative_path)
|
||||
.await?;
|
||||
|
||||
Ok(Response::builder()
|
||||
.status(StatusCode::OK)
|
||||
.header(header::CONTENT_TYPE, &asset.mime_type)
|
||||
.header(header::CONTENT_LENGTH, data.len())
|
||||
.header(
|
||||
header::CONTENT_DISPOSITION,
|
||||
format!(
|
||||
"inline; filename=\"{}\"",
|
||||
asset
|
||||
.source_reference
|
||||
.relative_path
|
||||
.rsplit('/')
|
||||
.next()
|
||||
.unwrap_or("file")
|
||||
),
|
||||
)
|
||||
.body(Body::from(data))
|
||||
.unwrap())
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ pub fn api_v1_router() -> Router<AppState> {
|
||||
.route("/assets/timeline", get(assets::timeline))
|
||||
.route("/assets/{id}", get(assets::get_asset))
|
||||
.route("/assets/{id}/metadata", put(assets::update_metadata))
|
||||
.route("/assets/{id}/file", get(assets::serve_file))
|
||||
// storage
|
||||
.route("/storage/volumes", post(storage::register_volume))
|
||||
.route(
|
||||
|
||||
@@ -6,7 +6,7 @@ use application::{
|
||||
};
|
||||
use std::sync::Arc;
|
||||
|
||||
use domain::ports::{StoragePort, TokenIssuer};
|
||||
use domain::ports::{AssetRepository, FileStoragePort, StoragePort, TokenIssuer};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct AppState {
|
||||
@@ -24,6 +24,8 @@ pub struct AppState {
|
||||
pub update_metadata_handler: Arc<UpdateMetadataHandler>,
|
||||
pub register_volume_handler: Arc<RegisterVolumeHandler>,
|
||||
pub register_library_path_handler: Arc<RegisterLibraryPathHandler>,
|
||||
pub file_storage: Arc<dyn FileStoragePort>,
|
||||
pub asset_repo: Arc<dyn AssetRepository>,
|
||||
}
|
||||
|
||||
impl AppState {
|
||||
@@ -43,6 +45,8 @@ impl AppState {
|
||||
update_metadata_handler: Arc<UpdateMetadataHandler>,
|
||||
register_volume_handler: Arc<RegisterVolumeHandler>,
|
||||
register_library_path_handler: Arc<RegisterLibraryPathHandler>,
|
||||
file_storage: Arc<dyn FileStoragePort>,
|
||||
asset_repo: Arc<dyn AssetRepository>,
|
||||
) -> Self {
|
||||
Self {
|
||||
register_handler,
|
||||
@@ -59,6 +63,8 @@ impl AppState {
|
||||
update_metadata_handler,
|
||||
register_volume_handler,
|
||||
register_library_path_handler,
|
||||
file_storage,
|
||||
asset_repo,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user