WIP moved templating engine to mycelium

This commit is contained in:
Slatian 2023-10-29 18:43:44 +01:00
parent 5ac056ef99
commit 5adca4fb80
4 changed files with 70 additions and 34 deletions

View File

@ -44,7 +44,6 @@ mod mycelium;
mod ratelimit; mod ratelimit;
mod settings; mod settings;
mod simple_dns; mod simple_dns;
mod templating_engine;
mod view; mod view;
use crate::geoip::{ use crate::geoip::{
@ -54,11 +53,14 @@ use crate::geoip::{
LocationResult, LocationResult,
}; };
use crate::idna::IdnaName; use crate::idna::IdnaName;
use crate::mycelium::MycEngine;
use crate::simple_dns::DnsLookupResult; use crate::simple_dns::DnsLookupResult;
use crate::settings::*; use crate::settings::*;
use crate::view::View; use crate::view::View;
use crate::ipinfo::{AddressCast,AddressInfo,AddressScope}; use crate::ipinfo::{AddressCast,AddressInfo,AddressScope};
type TemplatingEngine = MycEngine<View,QuerySettings,ResponseFormat>;
#[derive(Deserialize, Serialize, Clone)] #[derive(Deserialize, Serialize, Clone)]
pub struct SettingsQuery { pub struct SettingsQuery {
format: Option<ResponseFormat>, format: Option<ResponseFormat>,
@ -95,7 +97,7 @@ pub struct DigResult {
} }
struct ServiceSharedState { struct ServiceSharedState {
templating_engine: templating_engine::Engine, templating_engine: TemplatingEngine,
dns_resolvers: HashMap<Arc<str>,TokioAsyncResolver>, dns_resolvers: HashMap<Arc<str>,TokioAsyncResolver>,
dns_resolver_aliases: HashMap<Arc<str>,Arc<str>>, dns_resolver_aliases: HashMap<Arc<str>,Arc<str>>,
asn_db: geoip::MMDBCarrier, asn_db: geoip::MMDBCarrier,
@ -201,10 +203,10 @@ async fn main() {
} }
}; };
let templating_engine = templating_engine::Engine{ let templating_engine = TemplatingEngine::new(
tera: tera, tera,
template_config: template_extra_config, template_extra_config,
}; );
// Static file directory // Static file directory

View File

@ -1,7 +1,3 @@
/*
* This is the echoip-slatecave templating engine.
* It wraps around tera in is specialized for echoip-slatecave.
*/
use axum::{ use axum::{
body::{Bytes,Full}, body::{Bytes,Full},
@ -12,38 +8,55 @@ use axum::{
response::IntoResponse, response::IntoResponse,
response::Response, response::Response,
}; };
use axum_extra::extract::cookie::Cookie;
use axum_extra::extract::cookie;
use tera::Tera; use tera::Tera;
use toml::Table; use toml::Table;
use crate::view::View; use std::marker::PhantomData;
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::mycelium::MycQuerySettings;
use crate::settings::QuerySettings;
/* The engine itself */ /* The engine itself */
#[derive(Clone)] #[derive(Clone)]
pub struct Engine { pub struct MycEngine<V, S, F>
where V: MycView<S, F>, S: MycQuerySettings<F>, F: MycFormat {
pub tera: Tera, pub tera: Tera,
pub template_config: Option<Table>, pub template_config: Option<Table>,
phantom_view: PhantomData<V>,
phantom_settings: PhantomData<S>,
phantom_format: PhantomData<F>,
} }
impl Engine { impl<V, S, F> MycEngine<V, S, F>
where V: MycView<S, F>, S: MycQuerySettings<F>, F: MycFormat {
pub fn new(tera: Tera, template_config: Option<Table>) -> Self {
Self {
tera: tera,
template_config: template_config,
phantom_view: PhantomData,
phantom_settings: PhantomData,
phantom_format: PhantomData,
}
}
/// Takes settings and a view, converting it to a serveable response.
pub async fn render_view( pub async fn render_view(
&self, &self,
settings: &QuerySettings, settings: &S,
view: View, view: V,
) -> Response { ) -> Response {
let status_code = view.get_status_code(&settings); let status_code = view.get_status_code(&settings);
let cookie_string = view.get_cookie_header(&settings);
let format = settings.get_format();
let mut response = match settings.format.get_family() { let mut response = match format.get_family() {
MycFormatFamily::Template => { MycFormatFamily::Template => {
let template_name = view.get_template_name(); let template_name = view.get_template_name();
let format = settings.get_format();
let mime_type = format.get_mime_type(); let mime_type = format.get_mime_type();
let mut context = tera::Context::new(); let mut context = tera::Context::new();
@ -81,22 +94,29 @@ impl Engine {
view.get_api_response(&settings) view.get_api_response(&settings)
} }
}; };
// Everything went well and nobody did the following work for us.
if response.status() == StatusCode::OK {
// Set status code // Set status code
if response.status() == StatusCode::OK && status_code != StatusCode::OK { if status_code != StatusCode::OK {
*response.status_mut() = status_code; *response.status_mut() = status_code;
} }
// Set cookies
let cookie = Cookie::build("dns_resolver",settings.dns_resolver_id.to_string()) // Set cookie header
.path("/") if let Some(cookie_string) = cookie_string {
.same_site(cookie::SameSite::Strict) if let Ok(header_value) = HeaderValue::from_str(&cookie_string) {
.finish();
if let Ok(header_value) = HeaderValue::from_str(&cookie.to_string()) {
response.headers_mut().append( response.headers_mut().append(
SET_COOKIE, SET_COOKIE,
header_value, header_value,
); );
} }
}
}
// return response // return response
response response
} }
} }

View File

@ -1,7 +1,9 @@
mod engine;
mod format; mod format;
mod query_settings; mod query_settings;
mod view; mod view;
pub use self::engine::MycEngine;
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;

View File

@ -3,6 +3,8 @@ use axum::http::status::StatusCode;
use axum::Json; use axum::Json;
use axum::response::IntoResponse; use axum::response::IntoResponse;
use axum::response::Response; use axum::response::Response;
use axum_extra::extract::cookie::Cookie;
use axum_extra::extract::cookie;
use crate::DigResult; use crate::DigResult;
use crate::IpResult; use crate::IpResult;
@ -47,6 +49,16 @@ impl MycView<QuerySettings, ResponseFormat> for View {
} }
} }
fn get_cookie_header(&self, settings: &QuerySettings) -> Option<String> {
Some(
Cookie::build("dns_resolver",settings.dns_resolver_id.to_string())
.path("/")
.same_site(cookie::SameSite::Strict)
.finish()
.to_string()
)
}
fn get_api_response(self, settings: &QuerySettings) -> Response { fn get_api_response(self, settings: &QuerySettings) -> Response {
match self { match self {
Self::Dig{result, ..} => { Self::Dig{result, ..} => {