75 lines
1.8 KiB
Rust
75 lines
1.8 KiB
Rust
use axum::{
|
|
extract::{Query, State},
|
|
http::{StatusCode, header},
|
|
response::{IntoResponse, Response},
|
|
};
|
|
use pile_config::Label;
|
|
use pile_value::value::AsyncReader;
|
|
use serde::Deserialize;
|
|
use std::{sync::Arc, time::Instant};
|
|
use tracing::debug;
|
|
use utoipa::ToSchema;
|
|
|
|
use crate::Datasets;
|
|
|
|
#[derive(Deserialize, ToSchema)]
|
|
pub struct ItemQuery {
|
|
source: String,
|
|
key: String,
|
|
}
|
|
|
|
/// Fetch the raw bytes of an item by source and key
|
|
#[utoipa::path(
|
|
get,
|
|
path = "/item",
|
|
params(
|
|
("source" = String, Query, description = "Source label"),
|
|
("key" = String, Query, description = "Item key"),
|
|
),
|
|
responses(
|
|
(status = 200, description = "Raw item bytes"),
|
|
(status = 400, description = "Invalid source label"),
|
|
(status = 404, description = "Item not found"),
|
|
(status = 500, description = "Internal server error"),
|
|
)
|
|
)]
|
|
pub async fn item_get(
|
|
State(state): State<Arc<Datasets>>,
|
|
Query(params): Query<ItemQuery>,
|
|
) -> Response {
|
|
let start = Instant::now();
|
|
debug!(
|
|
message = "Serving /item",
|
|
source = params.source,
|
|
key = params.key
|
|
);
|
|
|
|
let label = match Label::try_from(params.source.clone()) {
|
|
Ok(l) => l,
|
|
Err(e) => return (StatusCode::BAD_REQUEST, format!("{e:?}")).into_response(),
|
|
};
|
|
|
|
let Some(item) = state.get(&label, ¶ms.key).await else {
|
|
return StatusCode::NOT_FOUND.into_response();
|
|
};
|
|
|
|
let mime = item.mime().to_string();
|
|
|
|
let mut reader = match item.read().await {
|
|
Ok(r) => r,
|
|
Err(e) => return (StatusCode::INTERNAL_SERVER_ERROR, format!("{e:?}")).into_response(),
|
|
};
|
|
|
|
debug!(
|
|
message = "Served /item",
|
|
source = params.source,
|
|
key = params.key,
|
|
time_ms = start.elapsed().as_millis()
|
|
);
|
|
|
|
match reader.read_to_end().await {
|
|
Ok(bytes) => (StatusCode::OK, [(header::CONTENT_TYPE, mime)], bytes).into_response(),
|
|
Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, format!("{e:?}")).into_response(),
|
|
}
|
|
}
|