1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
use crate::TeraHandler;
use serde::Serialize;
use tera::{Context, Tera};
use trillium::{Conn, KnownHeaderName};
/**
Extends trillium::Conn with tera template-rendering functionality.
*/
pub trait TeraConnExt {
/// Adds a key-value pair to the assigns [`Context`], where the key is
/// a &str and the value is any [`Serialize`] type.
fn assign(self, key: &str, value: impl Serialize) -> Self;
/// Uses the accumulated assigns context to render the template by
/// registered name to the conn body and return the conn. Halts
/// and sets a 200 status on successful render. Must be run
/// downsequence of the [`TeraHandler`], and will panic if the
/// TeraHandler has not already been called.
fn render(self, template: &str) -> Self;
/// Retrieves a reference to the [`Tera`] instance. Must be called
/// downsequence of the [`TeraHandler`], and will panic if the
/// TeraHandler has not already been called.
fn tera(&self) -> &Tera;
/// retrieves a reference to the tera assigns context. must be run
/// downsequence of the [`TeraHandler`], and will panic if the
/// TeraHandler has not already been called.
fn context_mut(&mut self) -> &mut Context;
/// Retrieves a reference to the tera assigns context. Must be run
/// downsequence of the [`TeraHandler`], and will panic if the
/// TeraHandler has not already been called.
fn context(&self) -> &Context;
}
impl TeraConnExt for Conn {
fn assign(mut self, key: &str, value: impl Serialize) -> Self {
self.context_mut().insert(key, &value);
self
}
fn tera(&self) -> &Tera {
self.state::<TeraHandler>()
.expect("tera must be run after the tera handler")
.tera()
}
fn context_mut(&mut self) -> &mut Context {
self.state_mut()
.expect("context_mut must be run after the tera handler")
}
fn context(&self) -> &Context {
self.state()
.expect("context must be run after the tera handler")
}
fn render(mut self, template_name: &str) -> Self {
let context = self.context();
match self.tera().render(template_name, context) {
Ok(string) => {
if let Some(mime) = mime_guess::from_path(template_name).first_raw() {
self.response_headers_mut()
.try_insert(KnownHeaderName::ContentType, mime);
}
self.ok(string)
}
Err(e) => {
log::error!("{:?}", &e);
self.with_status(500).with_body(e.to_string())
}
}
}
}