implemented text query logic

This commit is contained in:
Slatian 2023-02-22 23:07:43 +01:00
parent 5a27eb793d
commit e3054e0158
4 changed files with 46 additions and 13 deletions

2
Cargo.lock generated
View File

@ -1190,7 +1190,9 @@ dependencies = [
"axum", "axum",
"axum-client-ip", "axum-client-ip",
"clap", "clap",
"lazy_static",
"maxminddb", "maxminddb",
"regex",
"serde", "serde",
"tera", "tera",
"tokio", "tokio",

View File

@ -10,6 +10,8 @@ authors = ["Slatian <baschdel@disroot.org>"]
axum = { version = "0.6", features = ["macros", "headers"] } axum = { version = "0.6", features = ["macros", "headers"] }
axum-client-ip = "0.4" axum-client-ip = "0.4"
clap = { version = "4", features = ["derive"] } clap = { version = "4", features = ["derive"] }
lazy_static = "1.4.0"
regex = "1.7"
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }
tokio = { version = "1", features = ["full"] } tokio = { version = "1", features = ["full"] }
tera = "1" tera = "1"

View File

@ -15,6 +15,8 @@ use axum::{
}; };
use axum_client_ip::SecureClientIp; use axum_client_ip::SecureClientIp;
use clap::Parser; use clap::Parser;
use lazy_static::lazy_static;
use regex::Regex;
use tera::Tera; use tera::Tera;
use tower::ServiceBuilder; use tower::ServiceBuilder;
use trust_dns_resolver::{ use trust_dns_resolver::{
@ -60,6 +62,7 @@ pub struct SearchQuery {
#[derive(serde::Deserialize, serde::Serialize, Clone)] #[derive(serde::Deserialize, serde::Serialize, Clone)]
pub struct IpResult { pub struct IpResult {
address: IpAddr,
hostname: Option<String>, hostname: Option<String>,
asn: Option<AsnResult>, asn: Option<AsnResult>,
location: Option<LocationResult>, location: Option<LocationResult>,
@ -296,6 +299,10 @@ async fn handle_default_route(
let state = Arc::clone(&arc_state); let state = Arc::clone(&arc_state);
if let Some(search_query) = search_query.query {
return handle_search_request(search_query, false, settings, state).await;
}
let result = get_ip_result(&address, &settings.lang, &state).await; let result = get_ip_result(&address, &settings.lang, &state).await;
let user_agent: Option<String> = match user_agent_header { let user_agent: Option<String> = match user_agent_header {
@ -306,26 +313,46 @@ async fn handle_default_route(
state.templating_engine.render_view( state.templating_engine.render_view(
&settings, &settings,
&View::Index{ &View::Index{
query: address,
result: result, result: result,
user_agent: user_agent, user_agent: user_agent,
} }
).await ).await
} }
async fn handle_search_request( async fn handle_search_request(
search_query: String, search_query: String,
this_should_have_been_an_ip: bool, _this_should_have_been_an_ip: bool,
settings: TemplateSettings, settings: TemplateSettings,
arc_state: Arc<ServiceSharedState>, arc_state: Arc<ServiceSharedState>,
) -> Response { ) -> Response {
let state = Arc::clone(&arc_state); let search_query = search_query.trim();
state.templating_engine.render_view( lazy_static!{
&settings, static ref ASN_REGEX: Regex = Regex::new(r"^[Aa][Ss][Nn]?\s*(\d{1,7})$").unwrap();
&View::Message{title: "Your Search query was:".to_string(), message: search_query} }
).await
//If someone asked for an asn, give an asn answer
if let Some(asn_cap) = ASN_REGEX.captures(&search_query) {
if let Some(asn) = asn_cap.get(1).map_or(None, |m| m.as_str().parse::<u32>().ok()) {
// Render a dummy template that can at least link to other pages
let state = Arc::clone(&arc_state);
return state.templating_engine.render_view(
&settings,
&View::Asn{asn: asn},
).await
}
}
// Try to interpret as an IP-Address
if let Ok(address) = search_query.parse() {
return handle_ip_request(address, settings, arc_state).await;
}
// Fall back to treating it as a hostname
return handle_dig_request(search_query.to_string(), settings, arc_state).await
} }
async fn handle_ip_route_with_path( async fn handle_ip_route_with_path(
@ -351,7 +378,7 @@ async fn handle_ip_request(
state.templating_engine.render_view( state.templating_engine.render_view(
&settings, &settings,
&View::Ip{query: address, result: result} &View::Ip{result: result}
).await ).await
} }
@ -366,6 +393,7 @@ async fn get_ip_result(
if !(ip_info.scope == AddressScope::Global || ip_info.scope == AddressScope::Shared) || ip_info.cast != AddressCast::Unicast { if !(ip_info.scope == AddressScope::Global || ip_info.scope == AddressScope::Shared) || ip_info.cast != AddressCast::Unicast {
if !((ip_info.scope == AddressScope::Private || ip_info.scope == AddressScope::LinkLocal) && state.config.server.allow_private_ip_lookup) { if !((ip_info.scope == AddressScope::Private || ip_info.scope == AddressScope::LinkLocal) && state.config.server.allow_private_ip_lookup) {
return IpResult { return IpResult {
address: *address,
hostname: None, hostname: None,
asn: None, asn: None,
location: None, location: None,
@ -403,6 +431,7 @@ async fn get_ip_result(
}; };
IpResult{ IpResult{
address: *address,
hostname: final_hostname, hostname: final_hostname,
asn: asn_result, asn: asn_result,
location: location_result, location: location_result,

View File

@ -13,8 +13,6 @@ use axum::{
use tera::Tera; use tera::Tera;
use toml::Table; use toml::Table;
use std::net::IpAddr;
use crate::simple_dns; use crate::simple_dns;
use crate::IpResult; use crate::IpResult;
@ -53,9 +51,10 @@ pub struct TemplateSettings {
#[derive(serde::Deserialize, serde::Serialize, Clone)] #[derive(serde::Deserialize, serde::Serialize, Clone)]
#[serde(untagged)] #[serde(untagged)]
pub enum View { pub enum View {
Asn { asn: u32 },
Dig { query: String, result: simple_dns::DnsLookupResult }, Dig { query: String, result: simple_dns::DnsLookupResult },
Index { query: IpAddr, result: IpResult, user_agent: Option<String> }, Index { result: IpResult, user_agent: Option<String> },
Ip { query: IpAddr, result: IpResult }, Ip { result: IpResult },
Message{ title: String, message: String }, Message{ title: String, message: String },
#[serde(rename="404")] #[serde(rename="404")]
NotFound, NotFound,
@ -64,6 +63,7 @@ pub enum View {
impl View { impl View {
pub fn template_name(&self) -> String { pub fn template_name(&self) -> String {
match self { match self {
View::Asn{..} => "asn",
View::Dig{..} => "dig", View::Dig{..} => "dig",
View::Index{..} => "index", View::Index{..} => "index",
View::Ip{..} => "ip", View::Ip{..} => "ip",