Talon/src/assets.rs
ThetaDev 7f055c98be
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
feat: embedded UI
2023-03-28 01:14:27 +02:00

69 lines
2.3 KiB
Rust

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<String>) -> Result<Response> {
assets(request, path, PhantomData::<MenuAsset>)
}
fn assets<A: rust_embed::RustEmbed + Sync + Send>(
request: &Request,
path: Path<String>,
_: PhantomData<A>,
) -> Result<Response> {
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()),
}
}