use std::marker::PhantomData; use crate::{storage::CompressionAlg, util}; use poem::{ handler, http::{header, Method, StatusCode}, web::Path, Request, Response, Result, }; #[derive(rust_embed::RustEmbed)] #[folder = "ui/menu/dist/"] struct MenuAsset; #[handler] pub fn menu_assets(request: &Request, path: Path) -> Result { assets(request, path, PhantomData::) } fn assets( request: &Request, path: Path, _: PhantomData, ) -> Result { if request.method() != Method::GET { return Ok(StatusCode::METHOD_NOT_ALLOWED.into()); } let path = path.0; match A::get(&path) { Some(content) => { let hash = hex::encode(content.metadata.sha256_hash()); // if etag is matched, return 304 if request .headers() .get(header::IF_NONE_MATCH) .map(|etag| etag.to_str().unwrap_or("000000").eq(&hash)) .unwrap_or(false) { return Ok(StatusCode::NOT_MODIFIED.into()); } let alg = util::parse_accept_encoding(request.headers(), &[CompressionAlg::Brotli]); let (body, body_alg) = if let Some(CompressionAlg::Brotli) = alg { let path_compressed = format!("{path}.br"); if let Some(compressed_content) = MenuAsset::get(&path_compressed) { (compressed_content.data, CompressionAlg::Brotli) } else { (content.data, CompressionAlg::None) } } else { (content.data, CompressionAlg::None) }; // otherwise, return 200 with etag hash let mime = mime_guess::from_path(path).first_or_octet_stream(); let mut builder = Response::builder() .header(header::CONTENT_TYPE, mime.as_ref()) .header(header::ETAG, hash); if let Some(encoding) = body_alg.encoding() { builder = builder.header(header::CONTENT_ENCODING, encoding); } Ok(builder.body(body.to_vec())) } None => Ok(Response::builder().status(StatusCode::NOT_FOUND).finish()), } }