view image files
This commit is contained in:
102
backend/src/lib/inbound/http/handlers/warrens/fetch_file.rs
Normal file
102
backend/src/lib/inbound/http/handlers/warrens/fetch_file.rs
Normal file
@@ -0,0 +1,102 @@
|
||||
use axum::{
|
||||
body::Body,
|
||||
extract::{Query, State},
|
||||
};
|
||||
use base64::Engine as _;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use thiserror::Error;
|
||||
use tokio_util::io::ReaderStream;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::{
|
||||
domain::warren::{
|
||||
models::{
|
||||
auth_session::AuthRequest,
|
||||
file::{AbsoluteFilePathError, FilePath, FilePathError, FileStream},
|
||||
warren::FetchWarrenFileRequest,
|
||||
},
|
||||
ports::{AuthService, WarrenService},
|
||||
},
|
||||
inbound::http::{AppState, handlers::extractors::SessionIdHeader, responses::ApiError},
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, PartialEq, Hash)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(super) struct FetchWarrenFileHttpResponseBody {
|
||||
// base64 encoded file content bytes
|
||||
contents: String,
|
||||
}
|
||||
|
||||
impl From<Vec<u8>> for FetchWarrenFileHttpResponseBody {
|
||||
fn from(value: Vec<u8>) -> Self {
|
||||
Self {
|
||||
contents: base64::prelude::BASE64_STANDARD.encode(&value),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct FetchWarrenFileHttpRequestBody {
|
||||
warren_id: Uuid,
|
||||
path: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Error)]
|
||||
pub enum ParseFetchWarrenFileHttpRequestError {
|
||||
#[error(transparent)]
|
||||
FilePath(#[from] FilePathError),
|
||||
#[error(transparent)]
|
||||
AbsoluteFilePath(#[from] AbsoluteFilePathError),
|
||||
}
|
||||
|
||||
impl From<ParseFetchWarrenFileHttpRequestError> for ApiError {
|
||||
fn from(value: ParseFetchWarrenFileHttpRequestError) -> Self {
|
||||
match value {
|
||||
ParseFetchWarrenFileHttpRequestError::FilePath(err) => match err {
|
||||
FilePathError::InvalidPath => {
|
||||
ApiError::BadRequest("The file path must be valid".to_string())
|
||||
}
|
||||
},
|
||||
ParseFetchWarrenFileHttpRequestError::AbsoluteFilePath(err) => match err {
|
||||
AbsoluteFilePathError::NotAbsolute => {
|
||||
ApiError::BadRequest("The file path must be absolute".to_string())
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FetchWarrenFileHttpRequestBody {
|
||||
fn try_into_domain(
|
||||
self,
|
||||
) -> Result<FetchWarrenFileRequest, ParseFetchWarrenFileHttpRequestError> {
|
||||
let path = FilePath::new(&self.path)?.try_into()?;
|
||||
|
||||
Ok(FetchWarrenFileRequest::new(self.warren_id, path))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FileStream> for Body {
|
||||
fn from(value: FileStream) -> Self {
|
||||
Body::from_stream::<ReaderStream<tokio::fs::File>>(value.into())
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn fetch_file<WS: WarrenService, AS: AuthService>(
|
||||
State(state): State<AppState<WS, AS>>,
|
||||
SessionIdHeader(session): SessionIdHeader,
|
||||
Query(request): Query<FetchWarrenFileHttpRequestBody>,
|
||||
) -> Result<Body, ApiError> {
|
||||
let domain_request = request.try_into_domain()?;
|
||||
|
||||
state
|
||||
.auth_service
|
||||
.fetch_warren_file(
|
||||
AuthRequest::new(session, domain_request),
|
||||
state.warren_service.as_ref(),
|
||||
)
|
||||
.await
|
||||
.map(|contents| contents.into())
|
||||
.map_err(ApiError::from)
|
||||
}
|
||||
Reference in New Issue
Block a user