mirror of
https://codeberg.org/slatian/service.echoip-slatecave.git
synced 2025-01-28 19:05:04 +01:00
Moved templating to its own module
This commit is contained in:
parent
febcb8b02e
commit
0193c24385
111
src/main.rs
111
src/main.rs
@ -1,11 +1,7 @@
|
||||
use axum::{
|
||||
extract::Query,
|
||||
extract::State,
|
||||
http::StatusCode,
|
||||
response::Html,
|
||||
response::IntoResponse,
|
||||
response::Response,
|
||||
response::Json,
|
||||
Router,
|
||||
routing::get,
|
||||
};
|
||||
@ -16,82 +12,37 @@ use trust_dns_resolver::{
|
||||
config::ResolverConfig,
|
||||
};
|
||||
|
||||
|
||||
use std::net::{IpAddr, Ipv4Addr};
|
||||
use std::sync::Arc;
|
||||
|
||||
mod simple_dns;
|
||||
mod templating_engine;
|
||||
|
||||
#[derive(serde::Deserialize, serde::Serialize, Clone, Copy)]
|
||||
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()
|
||||
}
|
||||
}
|
||||
use crate::templating_engine::View;
|
||||
use crate::templating_engine::ResponseFormat;
|
||||
|
||||
#[derive(serde::Deserialize, serde::Serialize)]
|
||||
struct IpQuery {
|
||||
pub struct IpQuery {
|
||||
ip: Option<IpAddr>,
|
||||
format: Option<ResponseFormat>,
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize, serde::Serialize)]
|
||||
struct DigQuery {
|
||||
pub struct DigQuery {
|
||||
name: String,
|
||||
format: Option<ResponseFormat>,
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize, serde::Serialize)]
|
||||
struct IpResult {
|
||||
pub struct IpResult {
|
||||
hostname: Option<String>,
|
||||
}
|
||||
|
||||
struct TemplatingEngine {
|
||||
tera: Tera,
|
||||
}
|
||||
|
||||
struct ServiceSharedState {
|
||||
templating_engine: TemplatingEngine,
|
||||
templating_engine: templating_engine::Engine,
|
||||
dns_resolver: TokioAsyncResolver,
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize, serde::Serialize)]
|
||||
#[serde(untagged)]
|
||||
enum EchoipView {
|
||||
Dig { query: DigQuery, result: simple_dns::DnsLookupResult },
|
||||
Index { query: IpQuery, result: IpResult },
|
||||
Ip { query: IpQuery, result: IpResult },
|
||||
Message(String),
|
||||
#[serde(rename="404")]
|
||||
NotFound,
|
||||
}
|
||||
|
||||
impl EchoipView {
|
||||
fn template_name(&self) -> String {
|
||||
match self {
|
||||
EchoipView::Dig{..} => "dig",
|
||||
EchoipView::Index{..} => "index",
|
||||
EchoipView::Ip{..} => "ip",
|
||||
EchoipView::Message(..) => "message",
|
||||
EchoipView::NotFound => "404",
|
||||
}.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
// Initalize Tera templates
|
||||
@ -119,7 +70,7 @@ async fn main() {
|
||||
|
||||
// Initialize shared state
|
||||
let shared_state = Arc::new(ServiceSharedState{
|
||||
templating_engine: TemplatingEngine{
|
||||
templating_engine: templating_engine::Engine{
|
||||
tera: tera,
|
||||
},
|
||||
dns_resolver: dns_resolver,
|
||||
@ -148,50 +99,10 @@ async fn hello_world_handler(
|
||||
|
||||
state.templating_engine.render_view(
|
||||
ResponseFormat::TextPlain,
|
||||
EchoipView::Message("Hello! There, You, Awesome Creature!".to_string())
|
||||
View::Message("Hello! There, You, Awesome Creature!".to_string())
|
||||
).await
|
||||
}
|
||||
|
||||
impl TemplatingEngine {
|
||||
async fn render_view(
|
||||
&self,
|
||||
format: ResponseFormat,
|
||||
view: EchoipView,
|
||||
) -> Response {
|
||||
match format {
|
||||
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", &format.to_string());
|
||||
context.insert("data", &view);
|
||||
|
||||
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 {
|
||||
EchoipView::Dig{result, ..} => {
|
||||
Json(result).into_response()
|
||||
},
|
||||
EchoipView::Index{result, ..} | EchoipView::Ip{result, ..} => {
|
||||
Json(result).into_response()
|
||||
},
|
||||
_ => Json(view).into_response(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle_default_route(
|
||||
Query(ip_query): Query<IpQuery>,
|
||||
State(arc_state): State<Arc<ServiceSharedState>>,
|
||||
@ -211,7 +122,7 @@ async fn handle_default_route(
|
||||
|
||||
state.templating_engine.render_view(
|
||||
format,
|
||||
EchoipView::Index{query: ip_query, result: result}
|
||||
View::Index{query: ip_query, result: result}
|
||||
).await
|
||||
}
|
||||
|
||||
@ -228,7 +139,7 @@ async fn handle_dig_route(
|
||||
|
||||
state.templating_engine.render_view(
|
||||
format,
|
||||
EchoipView::Dig{ query: dig_query, result: dig_result}
|
||||
View::Dig{ query: dig_query, result: dig_result}
|
||||
).await
|
||||
|
||||
}
|
||||
|
111
src/templating_engine.rs
Normal file
111
src/templating_engine.rs
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
use crate::simple_dns;
|
||||
use crate::IpResult;
|
||||
use crate::IpQuery;
|
||||
use crate::DigQuery;
|
||||
|
||||
/* 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()
|
||||
}
|
||||
}
|
||||
|
||||
/* The echoip view */
|
||||
|
||||
#[derive(serde::Deserialize, serde::Serialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum View {
|
||||
Dig { query: DigQuery, result: simple_dns::DnsLookupResult },
|
||||
Index { query: IpQuery, result: IpResult },
|
||||
Ip { query: IpQuery, result: IpResult },
|
||||
Message(String),
|
||||
#[serde(rename="404")]
|
||||
NotFound,
|
||||
}
|
||||
|
||||
impl View {
|
||||
pub fn template_name(&self) -> String {
|
||||
match self {
|
||||
View::Dig{..} => "dig",
|
||||
View::Index{..} => "index",
|
||||
View::Ip{..} => "ip",
|
||||
View::Message(..) => "message",
|
||||
View::NotFound => "404",
|
||||
}.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
/* The engine itself */
|
||||
|
||||
pub struct Engine {
|
||||
pub tera: Tera,
|
||||
}
|
||||
|
||||
impl Engine {
|
||||
pub async fn render_view(
|
||||
&self,
|
||||
format: ResponseFormat,
|
||||
view: View,
|
||||
) -> Response {
|
||||
match format {
|
||||
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", &format.to_string());
|
||||
context.insert("data", &view);
|
||||
|
||||
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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user