breeze/src/view.rs

83 lines
2.0 KiB
Rust
Raw Normal View History

2022-12-28 22:05:28 -06:00
use std::{
ffi::OsStr,
path::{Component, PathBuf},
sync::Arc,
};
use axum::{
body::StreamBody,
extract::{Path, State},
2023-01-08 18:08:24 -06:00
http::HeaderValue,
response::{IntoResponse, Response},
2022-12-28 22:05:28 -06:00
};
2023-01-08 18:08:24 -06:00
2022-12-28 22:05:28 -06:00
use hyper::StatusCode;
2023-01-08 18:08:24 -06:00
use mime_guess::mime;
use tokio::fs::File;
2022-12-28 22:05:28 -06:00
use tokio_util::io::ReaderStream;
#[axum::debug_handler]
2022-12-28 22:05:28 -06:00
pub async fn view(
State(state): State<Arc<crate::state::AppState>>,
Path(original_path): Path<PathBuf>,
) -> Response {
// (hopefully) prevent path traversal, just check for any non-file components
if original_path
.components()
.into_iter()
.any(|x| !matches!(x, Component::Normal(_)))
{
2023-01-08 18:08:24 -06:00
error!(target: "view", "a request attempted path traversal");
2022-12-28 22:05:28 -06:00
return StatusCode::NOT_FOUND.into_response();
}
let name = original_path
.file_name()
.and_then(OsStr::to_str)
.unwrap_or_default()
.to_string();
2023-01-08 18:08:24 -06:00
let cache = state.cache.lock().await;
2022-12-28 22:05:28 -06:00
let cache_item = cache.get(&name);
2023-01-08 18:08:24 -06:00
if cache_item.is_none() {
let mut path = PathBuf::new();
path.push("uploads/");
path.push(name);
2022-12-28 22:05:28 -06:00
2023-01-08 18:08:24 -06:00
if !path.exists() || !path.is_file() {
return StatusCode::NOT_FOUND.into_response();
}
2022-12-28 22:05:28 -06:00
2023-01-08 18:08:24 -06:00
let file = File::open(path).await.unwrap();
2022-12-28 22:05:28 -06:00
2023-01-08 18:08:24 -06:00
let reader = ReaderStream::new(file);
let stream = StreamBody::new(reader);
info!(target: "view", "reading upload from disk");
return stream.into_response();
2022-12-28 22:05:28 -06:00
}
2023-01-08 18:08:24 -06:00
info!(target: "view", "reading upload from cache");
2022-12-28 22:05:28 -06:00
2023-01-08 18:08:24 -06:00
let data = cache_item.unwrap().clone();
2022-12-28 22:05:28 -06:00
2023-01-08 18:08:24 -06:00
let content_type = mime_guess::from_path(original_path)
.first()
.unwrap_or(mime::APPLICATION_OCTET_STREAM)
.to_string();
let mut res = data.into_response();
let headers = res.headers_mut();
headers.clear();
headers.insert(
"content-type",
HeaderValue::from_str(content_type.as_str()).unwrap(),
);
return res;
}