Added query settings to the generaliued templating mechanism

This commit is contained in:
Slatian 2023-10-29 18:10:57 +01:00
parent de179ea7fa
commit 51aa05fe13
7 changed files with 86 additions and 41 deletions

View File

@ -403,7 +403,7 @@ async fn not_found_handler(
state.templating_engine.render_view( state.templating_engine.render_view(
&settings, &settings,
&View::NotFound, View::NotFound,
).await ).await
} }
@ -415,7 +415,7 @@ async fn hello_world_handler(
state.templating_engine.render_view( state.templating_engine.render_view(
&settings, &settings,
&View::Message{ View::Message{
title: "Hey There!".to_string(), title: "Hey There!".to_string(),
message: "You,You are an awesome Creature!".to_string() message: "You,You are an awesome Creature!".to_string()
}, },
@ -459,7 +459,7 @@ async fn handle_default_route(
state.templating_engine.render_view( state.templating_engine.render_view(
&settings, &settings,
&View::Index{ View::Index{
result: result, result: result,
user_agent: user_agent, user_agent: user_agent,
} }
@ -489,7 +489,7 @@ async fn handle_search_request(
let state = Arc::clone(&arc_state); let state = Arc::clone(&arc_state);
return state.templating_engine.render_view( return state.templating_engine.render_view(
&settings, &settings,
&View::Asn{asn: asn}, View::Asn{asn: asn},
).await ).await
} }
} }
@ -528,7 +528,7 @@ async fn handle_dns_resolver_route(
let state = Arc::clone(&arc_state); let state = Arc::clone(&arc_state);
state.templating_engine.render_view( state.templating_engine.render_view(
&settings, &settings,
&View::DnsResolverList, View::DnsResolverList,
).await ).await
} }
@ -542,12 +542,12 @@ async fn handle_dns_resolver_route_with_path(
if let Some(resolver) = state.config.dns.resolver.get(query.as_str()) { if let Some(resolver) = state.config.dns.resolver.get(query.as_str()) {
state.templating_engine.render_view( state.templating_engine.render_view(
&settings, &settings,
&View::DnsResolver{ config: resolver.clone() }, View::DnsResolver{ config: resolver.clone() },
).await ).await
} else { } else {
state.templating_engine.render_view( state.templating_engine.render_view(
&settings, &settings,
&View::NotFound, View::NotFound,
).await ).await
} }
} }
@ -579,7 +579,7 @@ async fn handle_ip_request(
state.templating_engine.render_view( state.templating_engine.render_view(
&settings, &settings,
&View::Ip{result: result} View::Ip{result: result}
).await ).await
} }
@ -668,7 +668,7 @@ async fn handle_dig_request(
state.templating_engine.render_view( state.templating_engine.render_view(
&settings, &settings,
&View::Dig{ query: dig_query, result: dig_result} View::Dig{ query: dig_query, result: dig_result}
).await ).await
} }

View File

@ -1,7 +1,9 @@
mod format; mod format;
mod query_settings;
mod view; mod view;
pub use self::format::HtmlTextJsonFormat; pub use self::format::HtmlTextJsonFormat;
pub use self::format::MycFormat; pub use self::format::MycFormat;
pub use self::format::MycFormatFamily; pub use self::format::MycFormatFamily;
pub use self::query_settings::MycQuerySettings;
pub use self::view::MycView; pub use self::view::MycView;

View File

@ -0,0 +1,16 @@
use tera::Context;
use crate::mycelium::MycFormat;
pub trait MycQuerySettings<F>
where F: MycFormat {
/// Called before rendering a template to initalize it with
/// values that come from the query itself.
fn initalize_template_context(&self, context: &mut Context);
/// Returns the requested output format
fn get_format(&self) -> F;
}

View File

@ -4,7 +4,11 @@ use axum::response::Response;
use axum::http::status::StatusCode; use axum::http::status::StatusCode;
use serde::Serialize; use serde::Serialize;
pub trait MycView: Serialize + Sized { use crate::mycelium::MycQuerySettings;
use crate::mycelium::MycFormat;
pub trait MycView<S,F>: Serialize + Sized
where S: MycQuerySettings<F>, F: MycFormat {
/// Returns the template name that will be used to select /// Returns the template name that will be used to select
/// the template file. /// the template file.
@ -20,17 +24,17 @@ pub trait MycView: Serialize + Sized {
/// Returns the reponse code for the view. /// Returns the reponse code for the view.
/// ///
/// The numeric value will be useable as `http_status` in the template. /// The numeric value will be useable as `http_status` in the template.
fn get_status_code(&self) -> StatusCode; fn get_status_code(&self, settings: &S) -> StatusCode;
/// If this returns a String it will be used as the cookie header. /// If this returns a String it will be used as the cookie header.
/// ///
/// See: [axum: Constructing a Cookie](https://docs.rs/axum-extra/0.8.0/axum_extra/extract/cookie/struct.Cookie.html#constructing-a-cookie) /// See: [axum: Constructing a Cookie](https://docs.rs/axum-extra/0.8.0/axum_extra/extract/cookie/struct.Cookie.html#constructing-a-cookie)
fn get_cookie_header(&self) -> Option<String> { None } fn get_cookie_header(&self, _settings: &S) -> Option<String> { None }
/// Update non-API responses after they have been built. /// Update non-API responses after they have been built.
/// ///
/// Useful for setting extra headers. Does noting by default. /// Useful for setting extra headers. Does noting by default.
fn update_response(&self, _response: &mut Response) {} fn update_response(&self, _settings: &S, _response: &mut Response) {}
/// Return an API-Response /// Return an API-Response
/// ///
@ -41,7 +45,7 @@ pub trait MycView: Serialize + Sized {
/// advance and set on the reulting response if it has a status code of 200. /// advance and set on the reulting response if it has a status code of 200.
/// Otherwise it is assumed that the response genrating logic /// Otherwise it is assumed that the response genrating logic
/// alredy took care of that. /// alredy took care of that.
fn get_api_response(self) -> Response { fn get_api_response(self, _settings: &S) -> Response {
Json(self).into_response() Json(self).into_response()
} }
} }

View File

@ -2,6 +2,7 @@ use serde::{Deserialize,Serialize};
use std::sync::Arc; use std::sync::Arc;
use crate::mycelium::HtmlTextJsonFormat; use crate::mycelium::HtmlTextJsonFormat;
use crate::mycelium::MycQuerySettings;
/* Response format */ /* Response format */
@ -24,3 +25,16 @@ pub struct Selectable {
pub weight: i32, pub weight: i32,
} }
impl MycQuerySettings<ResponseFormat> for QuerySettings {
fn initalize_template_context(&self, context: &mut tera::Context) {
context.insert("language", &self.lang);
context.insert("dns_resolvers", &self.available_dns_resolvers);
context.insert("dns_resolver_id", &self.dns_resolver_id);
}
fn get_format(&self) -> ResponseFormat {
self.format.clone()
}
}

View File

@ -11,7 +11,6 @@ use axum::{
http::header::SET_COOKIE, http::header::SET_COOKIE,
response::IntoResponse, response::IntoResponse,
response::Response, response::Response,
response::Json,
}; };
use axum_extra::extract::cookie::Cookie; use axum_extra::extract::cookie::Cookie;
use axum_extra::extract::cookie; use axum_extra::extract::cookie;
@ -22,6 +21,7 @@ use crate::view::View;
use crate::mycelium::MycView; use crate::mycelium::MycView;
use crate::mycelium::MycFormat; use crate::mycelium::MycFormat;
use crate::mycelium::MycFormatFamily; use crate::mycelium::MycFormatFamily;
use crate::mycelium::MycQuerySettings;
use crate::settings::QuerySettings; use crate::settings::QuerySettings;
/* The engine itself */ /* The engine itself */
@ -36,25 +36,26 @@ impl Engine {
pub async fn render_view( pub async fn render_view(
&self, &self,
settings: &QuerySettings, settings: &QuerySettings,
view: &View, view: View,
) -> Response { ) -> Response {
let status_code = view.get_status_code(&settings);
let mut response = match settings.format.get_family() { let mut response = match settings.format.get_family() {
MycFormatFamily::Template => { MycFormatFamily::Template => {
let template_name = view.get_template_name(); let template_name = view.get_template_name();
let mime_type = settings.format.get_mime_type(); let format = settings.get_format();
let mime_type = format.get_mime_type();
let mut context = tera::Context::new(); let mut context = tera::Context::new();
context.insert("view", &template_name); context.insert("view", &template_name);
//intented for shared macros //intented for shared macros
context.insert("format", &settings.format.get_name()); context.insert("format", &format.get_name());
context.insert("mimetype", &mime_type.to_string()); context.insert("mimetype", &mime_type.to_string());
context.insert("language", &settings.lang);
context.insert("dns_resolvers", &settings.available_dns_resolvers);
context.insert("dns_resolver_id", &settings.dns_resolver_id);
context.insert("data", &view); context.insert("data", &view);
context.insert("extra", &self.template_config); context.insert("extra", &self.template_config);
settings.initalize_template_context(&mut context);
match self.tera.render(&(template_name.clone()+&settings.format.get_file_extension()), &context) { match self.tera.render(&(template_name.clone()+&format.get_file_extension()), &context) {
Ok(text) => Ok(text) =>
( (
[( [(
@ -74,25 +75,10 @@ impl Engine {
} }
} }
MycFormatFamily::API => { MycFormatFamily::API => {
match view { view.get_api_response(&settings)
View::Dig{result, ..} => {
Json(result).into_response()
},
View::Index{result, ..} | View::Ip{result, ..} => {
Json(result).into_response()
},
View::DnsResolverList => {
Json(settings.available_dns_resolvers.clone()).into_response()
},
View::DnsResolver{ config } => {
Json(config).into_response()
}
_ => Json(view).into_response(),
}
} }
}; };
// Set status code // Set status code
let status_code = view.get_status_code();
if status_code != StatusCode::OK { if status_code != StatusCode::OK {
*response.status_mut() = status_code; *response.status_mut() = status_code;
} }

View File

@ -1,9 +1,14 @@
use axum::http::status::StatusCode; use axum::http::status::StatusCode;
use axum::Json;
use axum::response::IntoResponse;
use axum::response::Response;
use crate::DigResult; use crate::DigResult;
use crate::IpResult; use crate::IpResult;
use crate::config::DnsResolverConfig; use crate::config::DnsResolverConfig;
use crate::settings::QuerySettings;
use crate::settings::ResponseFormat;
use crate::mycelium::MycView; use crate::mycelium::MycView;
@ -21,7 +26,7 @@ pub enum View {
NotFound, NotFound,
} }
impl MycView for View { impl MycView<QuerySettings, ResponseFormat> for View {
fn get_template_name(&self) -> String { fn get_template_name(&self) -> String {
match self { match self {
View::Asn{..} => "asn", View::Asn{..} => "asn",
@ -35,11 +40,29 @@ impl MycView for View {
}.to_string() }.to_string()
} }
fn get_status_code(&self) -> StatusCode { fn get_status_code(&self, _: &QuerySettings) -> StatusCode {
match self { match self {
Self::NotFound => StatusCode::NOT_FOUND, Self::NotFound => StatusCode::NOT_FOUND,
_ => StatusCode::OK, _ => StatusCode::OK,
} }
} }
fn get_api_response(self, settings: &QuerySettings) -> Response {
match self {
Self::Dig{result, ..} => {
Json(result).into_response()
},
Self::Index{result, ..} | Self::Ip{result, ..} => {
Json(result).into_response()
},
Self::DnsResolverList => {
Json(settings.available_dns_resolvers.clone()).into_response()
},
Self::DnsResolver{ config } => {
Json(config).into_response()
}
_ => Json(self).into_response(),
}
}
} }