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(
&settings,
&View::NotFound,
View::NotFound,
).await
}
@ -415,7 +415,7 @@ async fn hello_world_handler(
state.templating_engine.render_view(
&settings,
&View::Message{
View::Message{
title: "Hey There!".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(
&settings,
&View::Index{
View::Index{
result: result,
user_agent: user_agent,
}
@ -489,7 +489,7 @@ async fn handle_search_request(
let state = Arc::clone(&arc_state);
return state.templating_engine.render_view(
&settings,
&View::Asn{asn: asn},
View::Asn{asn: asn},
).await
}
}
@ -528,7 +528,7 @@ async fn handle_dns_resolver_route(
let state = Arc::clone(&arc_state);
state.templating_engine.render_view(
&settings,
&View::DnsResolverList,
View::DnsResolverList,
).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()) {
state.templating_engine.render_view(
&settings,
&View::DnsResolver{ config: resolver.clone() },
View::DnsResolver{ config: resolver.clone() },
).await
} else {
state.templating_engine.render_view(
&settings,
&View::NotFound,
View::NotFound,
).await
}
}
@ -579,7 +579,7 @@ async fn handle_ip_request(
state.templating_engine.render_view(
&settings,
&View::Ip{result: result}
View::Ip{result: result}
).await
}
@ -668,7 +668,7 @@ async fn handle_dig_request(
state.templating_engine.render_view(
&settings,
&View::Dig{ query: dig_query, result: dig_result}
View::Dig{ query: dig_query, result: dig_result}
).await
}

View File

@ -1,7 +1,9 @@
mod format;
mod query_settings;
mod view;
pub use self::format::HtmlTextJsonFormat;
pub use self::format::MycFormat;
pub use self::format::MycFormatFamily;
pub use self::query_settings::MycQuerySettings;
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 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
/// the template file.
@ -20,17 +24,17 @@ pub trait MycView: Serialize + Sized {
/// Returns the reponse code for the view.
///
/// 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.
///
/// 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.
///
/// 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
///
@ -41,7 +45,7 @@ pub trait MycView: Serialize + Sized {
/// advance and set on the reulting response if it has a status code of 200.
/// Otherwise it is assumed that the response genrating logic
/// alredy took care of that.
fn get_api_response(self) -> Response {
fn get_api_response(self, _settings: &S) -> Response {
Json(self).into_response()
}
}

View File

@ -2,6 +2,7 @@ use serde::{Deserialize,Serialize};
use std::sync::Arc;
use crate::mycelium::HtmlTextJsonFormat;
use crate::mycelium::MycQuerySettings;
/* Response format */
@ -24,3 +25,16 @@ pub struct Selectable {
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,
response::IntoResponse,
response::Response,
response::Json,
};
use axum_extra::extract::cookie::Cookie;
use axum_extra::extract::cookie;
@ -22,6 +21,7 @@ use crate::view::View;
use crate::mycelium::MycView;
use crate::mycelium::MycFormat;
use crate::mycelium::MycFormatFamily;
use crate::mycelium::MycQuerySettings;
use crate::settings::QuerySettings;
/* The engine itself */
@ -36,25 +36,26 @@ impl Engine {
pub async fn render_view(
&self,
settings: &QuerySettings,
view: &View,
view: View,
) -> Response {
let status_code = view.get_status_code(&settings);
let mut response = match settings.format.get_family() {
MycFormatFamily::Template => {
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();
context.insert("view", &template_name);
//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("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("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) =>
(
[(
@ -74,25 +75,10 @@ impl Engine {
}
}
MycFormatFamily::API => {
match view {
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(),
}
view.get_api_response(&settings)
}
};
// Set status code
let status_code = view.get_status_code();
if status_code != StatusCode::OK {
*response.status_mut() = status_code;
}

View File

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