bobashare_web/api/v1/
info.rs1use axum::{
4 extract::{Path, State},
5 response::{IntoResponse, Response},
6 Json,
7};
8use bobashare::storage::file::OpenUploadError;
9use chrono::{DateTime, Utc};
10use displaydoc::Display;
11use hyper::StatusCode;
12use serde::Serialize;
13use thiserror::Error;
14use tracing::{event, instrument, Level};
15
16use super::ApiErrorExt;
17use crate::AppState;
18
19#[derive(Debug, Clone, Serialize)]
21pub struct InfoResponse {
22 pub id: String,
24 pub url: String,
26 pub direct_url: String,
28 pub filename: String,
30 pub mimetype: String,
32 pub creation_date: DateTime<Utc>,
34 pub expiry_date: Option<DateTime<Utc>>,
36 }
38
39#[derive(Debug, Error, Display)]
41pub enum InfoError {
42 NotFound,
44
45 InternalServer(#[from] anyhow::Error),
47}
48impl IntoResponse for InfoError {
49 fn into_response(self) -> Response {
50 let code = match self {
51 Self::NotFound => StatusCode::NOT_FOUND,
52 Self::InternalServer(_) => StatusCode::INTERNAL_SERVER_ERROR,
53 };
54
55 self.into_response_with_code(code)
56 }
57}
58
59#[instrument(skip(state))]
72pub async fn info(
73 state: State<&'static AppState>,
74 Path(id): Path<String>,
75) -> Result<impl IntoResponse, InfoError> {
76 event!(Level::DEBUG, id, "reading upload metadata");
77 let metadata = state
78 .backend
79 .read_upload_metadata(&id)
80 .await
81 .map_err(|e| match e {
82 OpenUploadError::NotFound(_) => InfoError::NotFound,
83 e => InfoError::InternalServer(
84 anyhow::Error::new(e).context("error reading upload metadata"),
85 ),
86 })?;
87
88 let url = state.base_url.join(&id).unwrap().to_string();
89 let direct_url = state.raw_url.join(&id).unwrap().to_string();
90 event!(Level::INFO, "successfully queried upload metadata");
91 Ok(Json(InfoResponse {
92 id,
93 url,
94 direct_url,
95 filename: metadata.filename,
96 mimetype: metadata.mimetype.to_string(),
97 creation_date: metadata.creation_date,
98 expiry_date: metadata.expiry_date,
99 }))
100}