refactor: change asset handling

read assets from the template state instead of path to be able to embed
them into the binary instead of reading them form a path
This commit is contained in:
Alexander Navarro 2025-03-12 12:46:18 -03:00
parent 3ff1f26cc4
commit 1871610770
4 changed files with 53 additions and 9 deletions

1
Cargo.lock generated
View file

@ -286,6 +286,7 @@ dependencies = [
"axum-sqlx-tx", "axum-sqlx-tx",
"chrono", "chrono",
"figment", "figment",
"mime_guess",
"minijinja", "minijinja",
"minijinja-embed", "minijinja-embed",
"notify", "notify",

View file

@ -9,6 +9,7 @@ axum-htmx = { version = "0.7.0", features = ["auto-vary", "serde", "guards"] }
axum-sqlx-tx = "0.10.0" axum-sqlx-tx = "0.10.0"
chrono = { version = "0.4.39", features = ["serde"] } chrono = { version = "0.4.39", features = ["serde"] }
figment = { version = "0.10.19", features = ["env", "toml"] } figment = { version = "0.10.19", features = ["env", "toml"] }
mime_guess = "2.0.5"
minijinja = { version = "2.7.0", features = ["loader"] } minijinja = { version = "2.7.0", features = ["loader"] }
minijinja-embed = "2.7.0" minijinja-embed = "2.7.0"
notify = "8.0.0" notify = "8.0.0"

View file

@ -6,7 +6,7 @@ use tracing::debug;
pub type Result<T> = std::result::Result<T, Error>; pub type Result<T> = std::result::Result<T, Error>;
pub type ResultTemplate = std::result::Result<Html<String>, Error>; pub type ResultTemplate = Result<Html<String>>;
#[derive(thiserror::Error, Debug)] #[derive(thiserror::Error, Debug)]
pub enum Error { pub enum Error {
@ -33,15 +33,35 @@ pub enum Error {
#[error(transparent)] #[error(transparent)]
Config(#[from] figment::Error), Config(#[from] figment::Error),
#[error("")]
HTTP(StatusCode),
}
impl From<StatusCode> for Error {
fn from(value: StatusCode) -> Self {
Self::HTTP(value)
}
} }
impl IntoResponse for Error { impl IntoResponse for Error {
fn into_response(self) -> axum::response::Response { fn into_response(self) -> axum::response::Response {
let (status, message) = match self { let catch_all = (
_ => (
StatusCode::INTERNAL_SERVER_ERROR, StatusCode::INTERNAL_SERVER_ERROR,
"An unexpected error has ocurred!", "An unexpected error has ocurred!",
), );
let (status, message) = match self {
Error::Template(ref error) => {
if let minijinja::ErrorKind::TemplateNotFound = error.kind() {
(
StatusCode::NOT_FOUND,
"The requested resource was not found.",
)
} else {
catch_all
}
}
_ => catch_all,
}; };
debug!(error = ?self); debug!(error = ?self);

View file

@ -1,17 +1,39 @@
use axum::{extract::State, response::Html, routing::get, Router}; use axum::{
extract::{Path, State},
http::{header, HeaderMap, HeaderValue},
response::Html,
routing::get,
Router,
};
use axum_htmx::HxRequest; use axum_htmx::HxRequest;
use chrono::Utc; use chrono::Utc;
use minijinja::context; use minijinja::context;
use serde::Serialize; use serde::Serialize;
use sqlx::prelude::FromRow; use sqlx::prelude::FromRow;
use tower_http::services::ServeDir;
use crate::{AppState, ResultTemplate, Tx}; use crate::{AppState, Result, ResultTemplate, Tx};
pub fn new() -> Router<AppState> { pub fn new() -> Router<AppState> {
Router::new() Router::new()
.route("/", get(handler_home)) .route("/", get(handler_home))
.nest_service("/assets", ServeDir::new("dist/assets")) .route("/assets/{*asset}", get(handle_assets))
}
async fn handle_assets(
State(state): State<AppState>,
Path(asset): Path<String>,
) -> Result<(HeaderMap, String)> {
let mut headers = HeaderMap::new();
let mime = mime_guess::from_path(&asset).first_raw();
if let Some(mime) = mime {
headers.insert(header::CONTENT_TYPE, HeaderValue::from_static(mime));
}
let template = state.tmpl_env.get_template(&format!("assets/{}", asset))?;
Ok((headers, template.render(context!())?))
} }
#[derive(FromRow, Debug, Serialize)] #[derive(FromRow, Debug, Serialize)]