echoip-slatecave/src/templating_engine.rs

125 lines
2.9 KiB
Rust
Raw Normal View History

2023-02-12 17:53:50 +01:00
/*
* This is the echoip-slatecave templating engine.
* It wraps around tera in is specialized for echoip-slatecave.
*/
use axum::{
http::StatusCode,
response::Html,
response::IntoResponse,
response::Response,
response::Json,
};
use tera::Tera;
2023-02-19 23:12:43 +01:00
use toml::Table;
2023-02-12 17:53:50 +01:00
use crate::simple_dns;
use crate::IpResult;
/* Response format */
#[derive(serde::Deserialize, serde::Serialize, Clone, Copy)]
pub enum ResponseFormat {
#[serde(rename="text/plain", alias="text")]
TextPlain,
#[serde(rename="text/html", alias="html")]
TextHtml,
#[serde(rename="application/json", alias="json")]
ApplicationJson,
}
impl ToString for ResponseFormat {
fn to_string(&self) -> String {
match self {
ResponseFormat::TextPlain => "text/plain",
ResponseFormat::TextHtml => "text/html",
ResponseFormat::ApplicationJson => "application/json",
}.to_string()
}
}
/* Template Settings */
#[derive(serde::Deserialize, serde::Serialize, Clone)]
pub struct TemplateSettings {
pub format: ResponseFormat,
pub lang: String,
}
2023-02-12 17:53:50 +01:00
/* The echoip view */
2023-02-21 00:06:49 +01:00
#[derive(serde::Deserialize, serde::Serialize, Clone)]
2023-02-12 17:53:50 +01:00
#[serde(untagged)]
pub enum View {
2023-02-22 23:07:43 +01:00
Asn { asn: u32 },
2023-02-22 21:32:10 +01:00
Dig { query: String, result: simple_dns::DnsLookupResult },
2023-02-22 23:07:43 +01:00
Index { result: IpResult, user_agent: Option<String> },
Ip { result: IpResult },
Message{ title: String, message: String },
2023-02-12 17:53:50 +01:00
#[serde(rename="404")]
NotFound,
}
impl View {
pub fn template_name(&self) -> String {
match self {
2023-02-22 23:07:43 +01:00
View::Asn{..} => "asn",
2023-02-12 17:53:50 +01:00
View::Dig{..} => "dig",
View::Index{..} => "index",
View::Ip{..} => "ip",
View::Message{..} => "message",
2023-02-12 17:53:50 +01:00
View::NotFound => "404",
}.to_string()
}
}
/* The engine itself */
2023-02-21 00:06:49 +01:00
#[derive(Clone)]
2023-02-12 17:53:50 +01:00
pub struct Engine {
pub tera: Tera,
2023-02-19 23:12:43 +01:00
pub template_config: Option<Table>,
2023-02-12 17:53:50 +01:00
}
impl Engine {
pub async fn render_view(
&self,
settings: &TemplateSettings,
2023-02-21 00:06:49 +01:00
view: &View,
2023-02-12 17:53:50 +01:00
) -> Response {
match settings.format {
2023-02-12 17:53:50 +01:00
ResponseFormat::TextHtml => {
let template_name = view.template_name();
let mut context = tera::Context::new();
context.insert("view", &template_name);
//intented for shared macros
context.insert("format", &settings.format.to_string());
context.insert("language", &settings.lang);
2023-02-12 17:53:50 +01:00
context.insert("data", &view);
2023-02-19 23:12:43 +01:00
context.insert("extra", &self.template_config);
2023-02-12 17:53:50 +01:00
match self.tera.render(&(template_name+".html"), &context) {
Ok(html) => Html(html).into_response(),
Err(e) => {
println!("There was an error while rendering index.html: {e:?}");
StatusCode::INTERNAL_SERVER_ERROR.into_response()
}
}
}
//TODO: Plain Text should have its own matcher
ResponseFormat::ApplicationJson | ResponseFormat::TextPlain => {
match view {
View::Dig{result, ..} => {
Json(result).into_response()
},
View::Index{result, ..} | View::Ip{result, ..} => {
Json(result).into_response()
},
_ => Json(view).into_response(),
}
}
}
}
}