mirror of
https://codeberg.org/slatian/service.echoip-slatecave.git
synced 2024-11-10 08:37:21 +01:00
Template passtrough for dns server information
This commit is contained in:
parent
cc6a025f89
commit
727d9a77cd
@ -64,5 +64,5 @@ burst = 15
|
|||||||
[dns.resolver.digitalcourage]
|
[dns.resolver.digitalcourage]
|
||||||
display_name = "Digitalcourage 3"
|
display_name = "Digitalcourage 3"
|
||||||
servers = ["5.9.164.112:853","[2a01:4f8:251:554::2]:853"]
|
servers = ["5.9.164.112:853","[2a01:4f8:251:554::2]:853"]
|
||||||
protocol = "Tls"
|
protocol = "tls"
|
||||||
tls_dns_name = "dns3.digitalcourage.de"
|
tls_dns_name = "dns3.digitalcourage.de"
|
||||||
|
@ -16,6 +16,7 @@ pub struct DnsConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Clone)]
|
#[derive(Deserialize, Serialize, Clone)]
|
||||||
|
#[serde(rename_all="lowercase")]
|
||||||
pub enum DnsProtocol {
|
pub enum DnsProtocol {
|
||||||
Udp,
|
Udp,
|
||||||
Tcp,
|
Tcp,
|
||||||
|
145
src/main.rs
145
src/main.rs
@ -50,13 +50,13 @@ use crate::geoip::{
|
|||||||
LocationResult,
|
LocationResult,
|
||||||
};
|
};
|
||||||
use crate::idna::IdnaName;
|
use crate::idna::IdnaName;
|
||||||
|
use crate::simple_dns::DnsLookupResult;
|
||||||
use crate::templating_engine::{
|
use crate::templating_engine::{
|
||||||
View,
|
View,
|
||||||
ResponseFormat,
|
ResponseFormat,
|
||||||
TemplateSettings,
|
TemplateSettings,
|
||||||
|
Selectable,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::ipinfo::{AddressCast,AddressInfo,AddressScope};
|
use crate::ipinfo::{AddressCast,AddressInfo,AddressScope};
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Clone)]
|
#[derive(Deserialize, Serialize, Clone)]
|
||||||
@ -85,6 +85,7 @@ pub struct IpResult {
|
|||||||
asn: Option<AsnResult>,
|
asn: Option<AsnResult>,
|
||||||
location: Option<LocationResult>,
|
location: Option<LocationResult>,
|
||||||
ip_info: AddressInfo,
|
ip_info: AddressInfo,
|
||||||
|
used_dns_resolver: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need this one to hide the partial lookup field when irelevant
|
// We need this one to hide the partial lookup field when irelevant
|
||||||
@ -97,18 +98,23 @@ pub struct DigResult {
|
|||||||
idn: IdnaName,
|
idn: IdnaName,
|
||||||
#[serde(skip_serializing_if = "not")]
|
#[serde(skip_serializing_if = "not")]
|
||||||
partial_lookup: bool,
|
partial_lookup: bool,
|
||||||
|
used_dns_resolver: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct ServiceSharedState {
|
struct ServiceSharedState {
|
||||||
templating_engine: templating_engine::Engine,
|
templating_engine: templating_engine::Engine,
|
||||||
//dns_resolver: TokioAsyncResolver,
|
|
||||||
dns_resolvers: HashMap<String,TokioAsyncResolver>,
|
dns_resolvers: HashMap<String,TokioAsyncResolver>,
|
||||||
asn_db: geoip::MMDBCarrier,
|
asn_db: geoip::MMDBCarrier,
|
||||||
location_db: geoip::MMDBCarrier,
|
location_db: geoip::MMDBCarrier,
|
||||||
config: config::EchoIpServiceConfig,
|
config: config::EchoIpServiceConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Stores configuration that is derived from the original configuration
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct DerivedConfiguration {
|
||||||
|
dns_resolver_selectables: Vec<Selectable>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
#[command(author, version, long_about="A web service that tells you your ip-address and more …")]
|
#[command(author, version, long_about="A web service that tells you your ip-address and more …")]
|
||||||
struct CliArgs {
|
struct CliArgs {
|
||||||
@ -234,6 +240,8 @@ async fn main() {
|
|||||||
// Initalize DNS resolver with os defaults
|
// Initalize DNS resolver with os defaults
|
||||||
println!("Initalizing dns resolver ...");
|
println!("Initalizing dns resolver ...");
|
||||||
|
|
||||||
|
let mut dns_resolver_selectables = Vec::<Selectable>::new();
|
||||||
|
|
||||||
println!("Initalizing System resolver ...");
|
println!("Initalizing System resolver ...");
|
||||||
let res = TokioAsyncResolver::tokio_from_system_conf();
|
let res = TokioAsyncResolver::tokio_from_system_conf();
|
||||||
//let res = TokioAsyncResolver::tokio(ResolverConfig::default(), ResolverOpts::default());
|
//let res = TokioAsyncResolver::tokio(ResolverConfig::default(), ResolverOpts::default());
|
||||||
@ -245,22 +253,39 @@ async fn main() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
dns_resolver_selectables.push(Selectable {
|
||||||
|
id: "default".to_string(),
|
||||||
|
name: "System".to_string()
|
||||||
|
});
|
||||||
|
|
||||||
//FIXME: Not release ready,must be configurable and have better error handling.
|
//FIXME: Not release ready,must be configurable and have better error handling.
|
||||||
println!("Initalizing Quad9 resolver ...");
|
println!("Initalizing Quad9 resolver ...");
|
||||||
let quad9_resolver = TokioAsyncResolver::tokio(
|
let quad9_resolver = TokioAsyncResolver::tokio(
|
||||||
trust_dns_resolver::config::ResolverConfig::quad9_tls(),
|
trust_dns_resolver::config::ResolverConfig::quad9_tls(),
|
||||||
Default::default()
|
Default::default()
|
||||||
).unwrap();
|
).unwrap();
|
||||||
|
dns_resolver_selectables.push(Selectable {
|
||||||
|
id: "quad9".to_string(),
|
||||||
|
name: "Quad9".to_string()
|
||||||
|
});
|
||||||
println!("Initalizing Google resolver ...");
|
println!("Initalizing Google resolver ...");
|
||||||
let google_resolver = TokioAsyncResolver::tokio(
|
let google_resolver = TokioAsyncResolver::tokio(
|
||||||
trust_dns_resolver::config::ResolverConfig::google(),
|
trust_dns_resolver::config::ResolverConfig::google(),
|
||||||
Default::default()
|
Default::default()
|
||||||
).unwrap();
|
).unwrap();
|
||||||
|
dns_resolver_selectables.push(Selectable {
|
||||||
|
id: "google".to_string(),
|
||||||
|
name: "Google".to_string()
|
||||||
|
});
|
||||||
println!("Initalizing Cloudflare resolver ...");
|
println!("Initalizing Cloudflare resolver ...");
|
||||||
let cloudflare_resolver = TokioAsyncResolver::tokio(
|
let cloudflare_resolver = TokioAsyncResolver::tokio(
|
||||||
trust_dns_resolver::config::ResolverConfig::cloudflare_tls(),
|
trust_dns_resolver::config::ResolverConfig::cloudflare_tls(),
|
||||||
Default::default()
|
Default::default()
|
||||||
).unwrap();
|
).unwrap();
|
||||||
|
dns_resolver_selectables.push(Selectable {
|
||||||
|
id: "cloudflare".to_string(),
|
||||||
|
name: "Cloudflare".to_string()
|
||||||
|
});
|
||||||
|
|
||||||
let mut dns_resolver_map: HashMap<String,TokioAsyncResolver> = HashMap::new();
|
let mut dns_resolver_map: HashMap<String,TokioAsyncResolver> = HashMap::new();
|
||||||
|
|
||||||
@ -271,6 +296,10 @@ async fn main() {
|
|||||||
Default::default()
|
Default::default()
|
||||||
).unwrap();
|
).unwrap();
|
||||||
dns_resolver_map.insert(key.clone(), resolver);
|
dns_resolver_map.insert(key.clone(), resolver);
|
||||||
|
dns_resolver_selectables.push(Selectable {
|
||||||
|
id: key.clone(),
|
||||||
|
name: resolver_config.display_name.clone(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
dns_resolver_map.insert("default".to_string(), dns_resolver);
|
dns_resolver_map.insert("default".to_string(), dns_resolver);
|
||||||
@ -292,6 +321,10 @@ async fn main() {
|
|||||||
config: config.clone(),
|
config: config.clone(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let derived_config = DerivedConfiguration {
|
||||||
|
dns_resolver_selectables: dns_resolver_selectables,
|
||||||
|
};
|
||||||
|
|
||||||
let signal_usr1_handlers_state = shared_state.clone();
|
let signal_usr1_handlers_state = shared_state.clone();
|
||||||
|
|
||||||
task::spawn(async move {
|
task::spawn(async move {
|
||||||
@ -317,6 +350,8 @@ async fn main() {
|
|||||||
.route("/", get(handle_default_route))
|
.route("/", get(handle_default_route))
|
||||||
.route("/dig/:name", get(handle_dig_route_with_path))
|
.route("/dig/:name", get(handle_dig_route_with_path))
|
||||||
.route("/ip/:address", get(handle_ip_route_with_path))
|
.route("/ip/:address", get(handle_ip_route_with_path))
|
||||||
|
.route("/dns_resolver/:resolver", get(handle_dns_resolver_route_with_path))
|
||||||
|
.route("/dns_resolver", get(handle_dns_resolver_route))
|
||||||
.route("/ua", get(user_agent_handler))
|
.route("/ua", get(user_agent_handler))
|
||||||
.route("/hi", get(hello_world_handler))
|
.route("/hi", get(hello_world_handler))
|
||||||
.fallback_service(
|
.fallback_service(
|
||||||
@ -331,6 +366,7 @@ async fn main() {
|
|||||||
config.ratelimit.per_minute, config.ratelimit.burst))
|
config.ratelimit.per_minute, config.ratelimit.burst))
|
||||||
.layer(middleware::from_fn(ratelimit::rate_limit_middleware))
|
.layer(middleware::from_fn(ratelimit::rate_limit_middleware))
|
||||||
.layer(Extension(config))
|
.layer(Extension(config))
|
||||||
|
.layer(Extension(derived_config))
|
||||||
.layer(middleware::from_fn(settings_query_middleware))
|
.layer(middleware::from_fn(settings_query_middleware))
|
||||||
)
|
)
|
||||||
;
|
;
|
||||||
@ -347,6 +383,7 @@ async fn main() {
|
|||||||
async fn settings_query_middleware<B>(
|
async fn settings_query_middleware<B>(
|
||||||
Query(query): Query<SettingsQuery>,
|
Query(query): Query<SettingsQuery>,
|
||||||
Extension(config): Extension<config::EchoIpServiceConfig>,
|
Extension(config): Extension<config::EchoIpServiceConfig>,
|
||||||
|
Extension(derived_config): Extension<DerivedConfiguration>,
|
||||||
user_agent_header: Option<TypedHeader<headers::UserAgent>>,
|
user_agent_header: Option<TypedHeader<headers::UserAgent>>,
|
||||||
mut req: Request<B>,
|
mut req: Request<B>,
|
||||||
next: Next<B>
|
next: Next<B>
|
||||||
@ -369,6 +406,7 @@ async fn settings_query_middleware<B>(
|
|||||||
template: TemplateSettings{
|
template: TemplateSettings{
|
||||||
format: format.unwrap_or(ResponseFormat::TextHtml),
|
format: format.unwrap_or(ResponseFormat::TextHtml),
|
||||||
lang: query.lang.unwrap_or("en".to_string()),
|
lang: query.lang.unwrap_or("en".to_string()),
|
||||||
|
available_dns_resolvers: derived_config.dns_resolver_selectables,
|
||||||
},
|
},
|
||||||
dns_resolver_id: query.dns.unwrap_or(config.dns.default_resolver),
|
dns_resolver_id: query.dns.unwrap_or(config.dns.default_resolver),
|
||||||
});
|
});
|
||||||
@ -377,24 +415,24 @@ async fn settings_query_middleware<B>(
|
|||||||
|
|
||||||
async fn not_found_handler(
|
async fn not_found_handler(
|
||||||
State(arc_state): State<Arc<ServiceSharedState>>,
|
State(arc_state): State<Arc<ServiceSharedState>>,
|
||||||
Extension(settings): Extension<TemplateSettings>,
|
Extension(settings): Extension<QuerySettings>,
|
||||||
) -> Response {
|
) -> Response {
|
||||||
let state = Arc::clone(&arc_state);
|
let state = Arc::clone(&arc_state);
|
||||||
|
|
||||||
state.templating_engine.render_view(
|
state.templating_engine.render_view(
|
||||||
&settings,
|
&settings.template,
|
||||||
&View::NotFound,
|
&View::NotFound,
|
||||||
).await
|
).await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn hello_world_handler(
|
async fn hello_world_handler(
|
||||||
State(arc_state): State<Arc<ServiceSharedState>>,
|
State(arc_state): State<Arc<ServiceSharedState>>,
|
||||||
Extension(settings): Extension<TemplateSettings>,
|
Extension(settings): Extension<QuerySettings>,
|
||||||
) -> Response {
|
) -> Response {
|
||||||
let state = Arc::clone(&arc_state);
|
let state = Arc::clone(&arc_state);
|
||||||
|
|
||||||
state.templating_engine.render_view(
|
state.templating_engine.render_view(
|
||||||
&settings,
|
&settings.template,
|
||||||
&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()
|
||||||
@ -499,6 +537,37 @@ async fn handle_search_request(
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn handle_dns_resolver_route(
|
||||||
|
Extension(settings): Extension<QuerySettings>,
|
||||||
|
State(arc_state): State<Arc<ServiceSharedState>>,
|
||||||
|
) -> Response {
|
||||||
|
let state = Arc::clone(&arc_state);
|
||||||
|
state.templating_engine.render_view(
|
||||||
|
&settings.template,
|
||||||
|
&View::DnsResolverList,
|
||||||
|
).await
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async fn handle_dns_resolver_route_with_path(
|
||||||
|
Extension(settings): Extension<QuerySettings>,
|
||||||
|
State(arc_state): State<Arc<ServiceSharedState>>,
|
||||||
|
extract::Path(query): extract::Path<String>,
|
||||||
|
) -> Response {
|
||||||
|
let state = Arc::clone(&arc_state);
|
||||||
|
if let Some(resolver) = state.config.dns.resolver.get(&query) {
|
||||||
|
state.templating_engine.render_view(
|
||||||
|
&settings.template,
|
||||||
|
&View::DnsResolver{ config: resolver.clone() },
|
||||||
|
).await
|
||||||
|
} else {
|
||||||
|
state.templating_engine.render_view(
|
||||||
|
&settings.template,
|
||||||
|
&View::NotFound,
|
||||||
|
).await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async fn handle_ip_route_with_path(
|
async fn handle_ip_route_with_path(
|
||||||
Extension(settings): Extension<QuerySettings>,
|
Extension(settings): Extension<QuerySettings>,
|
||||||
State(arc_state): State<Arc<ServiceSharedState>>,
|
State(arc_state): State<Arc<ServiceSharedState>>,
|
||||||
@ -547,20 +616,20 @@ async fn get_ip_result(
|
|||||||
asn: None,
|
asn: None,
|
||||||
location: None,
|
location: None,
|
||||||
ip_info: ip_info,
|
ip_info: ip_info,
|
||||||
|
used_dns_resolver: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// do reverse lookup
|
// do reverse lookup
|
||||||
let hostname = if state.config.dns.allow_reverse_lookup {
|
let mut hostname: Option<String> = None;
|
||||||
|
let mut used_dns_resolver: Option<String> = None;
|
||||||
|
if state.config.dns.allow_reverse_lookup {
|
||||||
if let Some(dns_resolver) = &state.dns_resolvers.get(dns_resolver_name) {
|
if let Some(dns_resolver) = &state.dns_resolvers.get(dns_resolver_name) {
|
||||||
simple_dns::reverse_lookup(&dns_resolver, &address).await
|
hostname = simple_dns::reverse_lookup(&dns_resolver, &address).await;
|
||||||
} else {
|
used_dns_resolver = Some(dns_resolver_name.clone());
|
||||||
None
|
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
// asn lookup
|
// asn lookup
|
||||||
let asn_result = state.asn_db.query_asn_for_ip(address);
|
let asn_result = state.asn_db.query_asn_for_ip(address);
|
||||||
@ -572,23 +641,20 @@ async fn get_ip_result(
|
|||||||
);
|
);
|
||||||
|
|
||||||
// filter reverse lookup
|
// filter reverse lookup
|
||||||
let final_hostname = match hostname {
|
if let Some(name) = &hostname {
|
||||||
Some(name) => {
|
if match_domain_hidden_list(&name, &state.config.dns.hidden_suffixes) {
|
||||||
if match_domain_hidden_list(&name, &state.config.dns.hidden_suffixes) {
|
hostname = None;
|
||||||
None
|
used_dns_resolver = None;
|
||||||
} else {
|
}
|
||||||
Some(name.to_owned())
|
}
|
||||||
}
|
|
||||||
},
|
|
||||||
None => None,
|
|
||||||
};
|
|
||||||
|
|
||||||
IpResult{
|
IpResult{
|
||||||
address: *address,
|
address: *address,
|
||||||
hostname: final_hostname,
|
hostname: hostname,
|
||||||
asn: asn_result,
|
asn: asn_result,
|
||||||
location: location_result,
|
location: location_result,
|
||||||
ip_info: ip_info,
|
ip_info: ip_info,
|
||||||
|
used_dns_resolver: used_dns_resolver,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -630,11 +696,23 @@ async fn get_dig_result(
|
|||||||
do_full_lookup: bool,
|
do_full_lookup: bool,
|
||||||
) -> DigResult {
|
) -> DigResult {
|
||||||
let name = &dig_query.trim().trim_end_matches(".").to_string();
|
let name = &dig_query.trim().trim_end_matches(".").to_string();
|
||||||
if match_domain_hidden_list(&name, &state.config.dns.hidden_suffixes) {
|
let idna_name = IdnaName::from_string(&name);
|
||||||
Default::default()
|
if let Some(dns_resolver) = &state.dns_resolvers.get(dns_resolver_name) {
|
||||||
} else {
|
if match_domain_hidden_list(&name, &state.config.dns.hidden_suffixes) {
|
||||||
if let Some(dns_resolver) = &state.dns_resolvers.get(dns_resolver_name) {
|
// Try to hide the fact that we didn't do dns resolution at all
|
||||||
let idna_name = IdnaName::from_string(&name);
|
// We resolve example.org as basic avoidance of timing sidechannels.
|
||||||
|
// WARNING: this timing sidechannel avoidance is very crude.
|
||||||
|
simple_dns::lookup(
|
||||||
|
&dns_resolver,
|
||||||
|
&("example.org.".to_string()),
|
||||||
|
do_full_lookup).await;
|
||||||
|
DigResult {
|
||||||
|
records: DnsLookupResult{ nxdomain: true , ..Default::default() },
|
||||||
|
idn: idna_name,
|
||||||
|
partial_lookup: !do_full_lookup,
|
||||||
|
used_dns_resolver: dns_resolver_name.clone(),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
DigResult {
|
DigResult {
|
||||||
records: simple_dns::lookup(
|
records: simple_dns::lookup(
|
||||||
&dns_resolver,
|
&dns_resolver,
|
||||||
@ -642,9 +720,10 @@ async fn get_dig_result(
|
|||||||
do_full_lookup).await,
|
do_full_lookup).await,
|
||||||
idn: idna_name,
|
idn: idna_name,
|
||||||
partial_lookup: !do_full_lookup,
|
partial_lookup: !do_full_lookup,
|
||||||
|
used_dns_resolver: dns_resolver_name.clone(),
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
return Default::default();
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
return Default::default();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,20 +27,20 @@ use std::net::IpAddr;
|
|||||||
|
|
||||||
#[derive(serde::Deserialize, serde::Serialize, Default, Clone)]
|
#[derive(serde::Deserialize, serde::Serialize, Default, Clone)]
|
||||||
pub struct DnsLookupResult {
|
pub struct DnsLookupResult {
|
||||||
a: Option<Vec<IpAddr>>,
|
pub a: Option<Vec<IpAddr>>,
|
||||||
aaaa: Option<Vec<IpAddr>>,
|
pub aaaa: Option<Vec<IpAddr>>,
|
||||||
aname: Option<Vec<String>>,
|
pub aname: Option<Vec<String>>,
|
||||||
cname: Option<Vec<String>>,
|
pub cname: Option<Vec<String>>,
|
||||||
mx: Option<Vec<MxRecord>>,
|
pub mx: Option<Vec<MxRecord>>,
|
||||||
ns: Option<Vec<String>>,
|
pub ns: Option<Vec<String>>,
|
||||||
soa: Option<Vec<SoaRecord>>,
|
pub soa: Option<Vec<SoaRecord>>,
|
||||||
txt: Option<Vec<String>>,
|
pub txt: Option<Vec<String>>,
|
||||||
srv: Option<Vec<SrvRecord>>,
|
pub srv: Option<Vec<SrvRecord>>,
|
||||||
caa: Option<Vec<String>>,
|
pub caa: Option<Vec<String>>,
|
||||||
other_error: bool,
|
pub other_error: bool,
|
||||||
dns_error: bool,
|
pub dns_error: bool,
|
||||||
nxdomain: bool,
|
pub nxdomain: bool,
|
||||||
timeout: bool,
|
pub timeout: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Deserialize, serde::Serialize, Clone, PartialEq)]
|
#[derive(serde::Deserialize, serde::Serialize, Clone, PartialEq)]
|
||||||
|
@ -15,6 +15,7 @@ use toml::Table;
|
|||||||
|
|
||||||
use crate::DigResult;
|
use crate::DigResult;
|
||||||
use crate::IpResult;
|
use crate::IpResult;
|
||||||
|
use crate::config::DnsResolverConfig;
|
||||||
|
|
||||||
/* Response format */
|
/* Response format */
|
||||||
|
|
||||||
@ -54,6 +55,13 @@ impl ResponseFormat {
|
|||||||
pub struct TemplateSettings {
|
pub struct TemplateSettings {
|
||||||
pub format: ResponseFormat,
|
pub format: ResponseFormat,
|
||||||
pub lang: String,
|
pub lang: String,
|
||||||
|
pub available_dns_resolvers: Vec<Selectable>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(serde::Deserialize, serde::Serialize, Clone)]
|
||||||
|
pub struct Selectable {
|
||||||
|
pub id: String,
|
||||||
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The echoip view */
|
/* The echoip view */
|
||||||
@ -63,6 +71,8 @@ pub struct TemplateSettings {
|
|||||||
pub enum View {
|
pub enum View {
|
||||||
Asn { asn: u32 },
|
Asn { asn: u32 },
|
||||||
Dig { query: String, result: DigResult },
|
Dig { query: String, result: DigResult },
|
||||||
|
DnsResolver{ config: DnsResolverConfig },
|
||||||
|
DnsResolverList,
|
||||||
Index { result: IpResult, user_agent: Option<String> },
|
Index { result: IpResult, user_agent: Option<String> },
|
||||||
Ip { result: IpResult },
|
Ip { result: IpResult },
|
||||||
Message{ title: String, message: String },
|
Message{ title: String, message: String },
|
||||||
@ -75,6 +85,8 @@ impl View {
|
|||||||
match self {
|
match self {
|
||||||
View::Asn{..} => "asn",
|
View::Asn{..} => "asn",
|
||||||
View::Dig{..} => "dig",
|
View::Dig{..} => "dig",
|
||||||
|
View::DnsResolver{..} => "dns_resolver",
|
||||||
|
View::DnsResolverList => "dns_resolver_list",
|
||||||
View::Index{..} => "index",
|
View::Index{..} => "index",
|
||||||
View::Ip{..} => "ip",
|
View::Ip{..} => "ip",
|
||||||
View::Message{..} => "message",
|
View::Message{..} => "message",
|
||||||
@ -133,6 +145,12 @@ impl Engine {
|
|||||||
View::Index{result, ..} | View::Ip{result, ..} => {
|
View::Index{result, ..} | View::Ip{result, ..} => {
|
||||||
Json(result).into_response()
|
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(),
|
_ => Json(view).into_response(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user