69 lines
2.3 KiB
Rust
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()),
|
|
}
|
|
}
|