feat: add file serving endpoint GET /assets/:id/file

This commit is contained in:
2026-05-31 05:59:19 +02:00
parent 3a18fd1d3f
commit 0f003a3bd6
4 changed files with 52 additions and 5 deletions

View File

@@ -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())
}

View File

@@ -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(

View File

@@ -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,
}
}
}