From aaaed7ce62907b2d99fe75b8a64058509519b474 Mon Sep 17 00:00:00 2001 From: itsscb Date: Sat, 21 Jun 2025 23:59:44 +0200 Subject: [PATCH] fix: recursive bloat in html the meta, title and style tags are being replicated in the list on '/' --- Cargo.toml | 3 +- src/lib.rs | 56 +++++++++++++++++++++++++++++------ src/main.rs | 10 ++++++- src/person.rs | 47 ++++++++++++++++++++++++++++- src/stammbaum.rs | 26 ++++++++++------ templates/person.html | 22 ++++++-------- templates/person_full.html | 38 ++++++++++++++++++++++++ templates/stammbaum.html | 36 ++++++++++++++++++++++ templates/stammbaum_full.html | 40 +++++++++++++++++++++++++ 9 files changed, 244 insertions(+), 34 deletions(-) create mode 100644 templates/person_full.html create mode 100644 templates/stammbaum.html create mode 100644 templates/stammbaum_full.html diff --git a/Cargo.toml b/Cargo.toml index e804d2e..e268a1d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,7 @@ chrono = { version = "0.4.41", features = ["serde"] } serde = { version = "1.0.219", features = ["derive", "rc"] } serde_json = "1.0.140" tokio = { version = "1.45.1", features = ["full", "tracing"] } +tower-http = { version = "0.6.6", features = ["trace"] } tracing = "0.1.41" -tracing-subscriber = "0.3.19" +tracing-subscriber = { version = "0.3.19", features = ["env-filter"] } uuid = { version = "1.17.0", features = ["serde", "v4"] } diff --git a/src/lib.rs b/src/lib.rs index f5f816b..6c03257 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,39 +3,75 @@ use askama::Template; use axum::{ Router, extract::{Path, State}, + http::HeaderMap, http::StatusCode, response::{Html, IntoResponse}, routing::get, serve, }; -use person::PersonID; -use stammbaum::Stammbaum; +use person::{PersonID, PersonTemplate, PersonTemplateFull}; +use stammbaum::{Stammbaum, StammbaumFull}; use std::io::BufReader; use tokio::runtime::Runtime; +use tower_http::trace::TraceLayer; +use tracing::{error, instrument, warn}; mod person; mod stammbaum; - +#[instrument(skip(stammbaum))] async fn get_person( Path(id): Path, + headers: HeaderMap, State(stammbaum): State, ) -> Result { let id = match PersonID::try_from(id) { Ok(id) => id, - Err(_) => return Err(StatusCode::INTERNAL_SERVER_ERROR), + Err(e) => { + error!(error = ?e); + return Err(StatusCode::INTERNAL_SERVER_ERROR); + } }; match stammbaum.get(id) { - None => Err(StatusCode::NOT_FOUND), - Some(p) => Ok(Html( - p.render().map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?, - )), + None => { + warn!(id = ?id, "not_found"); + Err(StatusCode::NOT_FOUND) + } + Some(p) => match headers.get("HX-Request") { + Some(_) => Ok(Html(PersonTemplate::from(p.to_owned()).render().map_err( + |e| { + error!(error=?e, id = ?id); + StatusCode::INTERNAL_SERVER_ERROR + }, + )?)), + _ => Ok(Html( + PersonTemplateFull::from(p.to_owned()) + .render() + .map_err(|e| { + error!(error=?e, id = ?id); + StatusCode::INTERNAL_SERVER_ERROR + })?, + )), + }, } } +#[instrument] async fn list_stammbaum( + headers: HeaderMap, State(stammbaum): State, ) -> Result { - Ok::, StatusCode>(Html(stammbaum.render())) + match headers.get("HX-Request") { + Some(_) => Ok::, StatusCode>(Html( + stammbaum + .render() + .expect("should have rendered the template"), + )), + None => Ok::, StatusCode>(Html( + StammbaumFull::from(stammbaum) + .render() + .expect("should have rendered the template"), + )), + } } pub fn run() -> Result<(), String> { @@ -50,7 +86,9 @@ pub fn run() -> Result<(), String> { let app = Router::new() .route("/", get(list_stammbaum)) .route("/{id}", get(get_person)) + .layer(TraceLayer::new_for_http()) .with_state(stammbaum); + let addr = tokio::net::TcpListener::bind("0.0.0.0:3000") .await .expect("faild to bind port"); diff --git a/src/main.rs b/src/main.rs index 75242da..655e873 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,13 @@ use stammbaum::run; +use tracing_subscriber::EnvFilter; +#[allow(clippy::unwrap_used)] fn main() { - #[allow(clippy::unwrap_used)] + tracing_subscriber::fmt() + .with_env_filter( + EnvFilter::try_from_default_env() + .or_else(|_| EnvFilter::try_new("stammbaum=debug")) + .unwrap(), + ) + .init(); run().unwrap(); } diff --git a/src/person.rs b/src/person.rs index 5397726..faacb04 100644 --- a/src/person.rs +++ b/src/person.rs @@ -7,8 +7,30 @@ use uuid::Uuid; pub type PersonID = Uuid; -#[derive(Template, Clone, Debug, Serialize, Deserialize)] +#[derive(Template)] #[template(path = "person.html")] +pub struct PersonTemplate { + person: Person, +} + +impl From for PersonTemplate { + fn from(value: Person) -> Self { + Self { person: value } + } +} +#[derive(Template)] +#[template(path = "person_full.html")] +pub struct PersonTemplateFull { + person: Person, +} + +impl From for PersonTemplateFull { + fn from(value: Person) -> Self { + Self { person: value } + } +} + +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct Person { id: PersonID, first_name: Arc, @@ -44,6 +66,29 @@ impl Person { } } + pub fn sex(&self) -> &Sex { + &self.sex + } + + pub fn date_of_birth(&self) -> DateTime { + self.date_of_birth + } + + pub fn maiden_name(&self) -> Option> { + self.maiden_name.clone() + } + + pub fn last_name(&self) -> Arc { + self.last_name.clone() + } + pub fn first_name(&self) -> Arc { + self.first_name.clone() + } + + pub fn parents(&self) -> &Vec { + &self.parents + } + pub fn add_parent(&mut self, parent: PersonID) { self.parents.push(parent); } diff --git a/src/stammbaum.rs b/src/stammbaum.rs index b0eac6f..da1335e 100644 --- a/src/stammbaum.rs +++ b/src/stammbaum.rs @@ -1,14 +1,29 @@ use serde::{Deserialize, Serialize}; -use crate::person::{Person, PersonID}; +use crate::person::{Person, PersonID, Sex}; use askama::Template; -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, Template)] +#[template(path = "stammbaum.html")] pub struct Stammbaum { members: Vec, } +#[derive(Template)] +#[template(path = "stammbaum_full.html")] +pub struct StammbaumFull { + members: Vec, +} + +impl From for StammbaumFull { + fn from(value: Stammbaum) -> Self { + Self { + members: value.members, + } + } +} + #[allow(dead_code)] impl Stammbaum { pub fn new(members: Vec) -> Self { @@ -18,13 +33,6 @@ impl Stammbaum { pub fn get(&self, id: PersonID) -> Option<&Person> { self.members.iter().find(|p| p.id() == id) } - - pub fn render(&self) -> String { - self.members - .iter() - .flat_map(|p: &Person| p.render()) - .collect() - } } mod test { diff --git a/templates/person.html b/templates/person.html index a37a02f..c58b446 100644 --- a/templates/person.html +++ b/templates/person.html @@ -1,31 +1,28 @@ -{% extends "_layout.html" %} - -{%- block content -%}
- {{ first_name }} - {{ last_name }} - {% if maiden_name.is_some() %} - ({{ maiden_name.as_ref().unwrap() }}) + {{ person.first_name }} + {{ person.last_name }} + {% if person.maiden_name.is_some() %} + ({{ person.maiden_name.as_ref().unwrap() }}) {% endif %}
Sex: - {% match sex %} + {% match person.sex %} {% when Sex::Male %}Male {% when Sex::Female %}Female {% when Sex::Other(desc) %}{{ desc }} {% endmatch %}
-
Birthday: {{ date_of_birth.format("%Y-%m-%d") }}
-ID: {{ id }} +
Birthday: {{ person.date_of_birth.format("%Y-%m-%d") }}
+ID: {{ person.id }}
Parents: - {% if parents.is_empty() %} + {% if person.parents.is_empty() %}
    {% else %}
      - {% for parent_id in &parents %} + {% for parent_id in &person.parents %}
    • {{ parent_id }} @@ -35,4 +32,3 @@ {% endif %}
    - {%- endblock -%} diff --git a/templates/person_full.html b/templates/person_full.html new file mode 100644 index 0000000..2e8f19a --- /dev/null +++ b/templates/person_full.html @@ -0,0 +1,38 @@ +{% extends "_layout.html" %} + +{%- block content -%} +
    +
    + {{ person.first_name }} + {{ person.last_name }} + {% if person.maiden_name.is_some() %} + ({{ person.maiden_name.as_ref().unwrap() }}) + {% endif %} +
    +
    +
    Sex: + {% match person.sex %} + {% when Sex::Male %}Male + {% when Sex::Female %}Female + {% when Sex::Other(desc) %}{{ desc }} + {% endmatch %} +
    +
    Birthday: {{ person.date_of_birth.format("%Y-%m-%d") }}
    +ID: {{ person.id }} +
    + Parents: + {% if person.parents.is_empty() %} +
      + {% else %} +
        + {% for parent_id in &person.parents %} +
      • +{{ parent_id }} + +
      • + {% endfor %} +
      + {% endif %} +
      +
      + {%- endblock -%} diff --git a/templates/stammbaum.html b/templates/stammbaum.html new file mode 100644 index 0000000..7d32eee --- /dev/null +++ b/templates/stammbaum.html @@ -0,0 +1,36 @@ +{% for person in members %} +
      +
      + {{ person.first_name() }} + {{ person.last_name() }} + {% if person.maiden_name().is_some() %} + ({{ person.maiden_name().as_ref().unwrap() }}) + {% endif %} +
      +
      +
      Sex: + {% match person.sex() %} + {% when Sex::Male %}Male + {% when Sex::Female %}Female + {% when Sex::Other(desc) %}{{ desc }} + {% endmatch %} +
      +
      Birthday: {{ person.date_of_birth().format("%Y-%m-%d") }}
      +ID: {{ person.id() }} +
      + Parents: + {% if person.parents().is_empty() %} +
        + {% else %} +
          + {% for parent_id in &person.parents() %} +
        • +{{ parent_id }} + +
        • + {% endfor %} +
        + {% endif %} +
        +
        +{% endfor %} diff --git a/templates/stammbaum_full.html b/templates/stammbaum_full.html new file mode 100644 index 0000000..c0a82b7 --- /dev/null +++ b/templates/stammbaum_full.html @@ -0,0 +1,40 @@ +{% extends "_layout.html" %} + +{%- block content -%} +{% for person in members %} +
        +
        + {{ person.first_name() }} + {{ person.last_name() }} + {% if person.maiden_name().is_some() %} + ({{ person.maiden_name().as_ref().unwrap() }}) + {% endif %} +
        +
        +
        Sex: + {% match person.sex() %} + {% when Sex::Male %}Male + {% when Sex::Female %}Female + {% when Sex::Other(desc) %}{{ desc }} + {% endmatch %} +
        +
        Birthday: {{ person.date_of_birth().format("%Y-%m-%d") }}
        +ID: {{ person.id() }} +
        + Parents: + {% if person.parents().is_empty() %} +
          + {% else %} +
            + {% for parent_id in &person.parents() %} +
          • +{{ parent_id }} + +
          • + {% endfor %} +
          + {% endif %} +
          +
          + {% endfor %} + {%- endblock -%}