move sanitize and parse

fmt dns

dns utils

fmt

unit test

unit test
This commit is contained in:
Luna Yao
2026-04-18 23:03:46 +02:00
parent ae4e9b3513
commit 185eb1e4c2
3 changed files with 66 additions and 47 deletions
+1 -1
View File
@@ -3,8 +3,8 @@ use crate::dns::config::zone::ZoneConfig;
use crate::dns::config::{DNS_DEFAULT_ADDRESS, DNS_DEFAULT_DOMAIN};
use crate::dns::server::DnsServer;
use crate::dns::utils::addr::NameServerAddrGroup;
use crate::dns::utils::parse;
use crate::proto::dns::GetExportConfigResponse;
use crate::utils::dns::parse;
use derivative::Derivative;
use hickory_net::xfer::Protocol;
use hickory_proto::rr::{LowerName, Name};
-39
View File
@@ -1,42 +1,3 @@
use hickory_proto::rr::LowerName;
use idna::AsciiDenyList;
pub mod addr;
pub mod response;
pub mod zone_handler;
pub fn sanitize(name: &str) -> String {
let dot = name.ends_with('.');
let mut name = idna::domain_to_ascii_cow(name.as_ref(), AsciiDenyList::EMPTY)
.unwrap_or_default()
.into_owned()
.to_lowercase()
.split('.')
.map(|label| {
label
.chars()
.map(|c| if c.is_ascii_alphanumeric() { c } else { '-' })
.take(63)
.collect::<String>()
.trim_matches('-')
.to_string()
})
.filter(|label| !label.is_empty())
.collect::<Vec<_>>()
.join(".");
name.truncate(253);
if dot {
name.push('.');
}
name
}
pub fn parse(name: &str) -> LowerName {
if let Ok(name) = name.parse() {
name
} else {
let sanitized = sanitize(name);
tracing::debug!("invalid name: {}, sanitized to: {}", name, sanitized);
sanitized.parse().unwrap_or_default()
}
}
+65 -7
View File
@@ -1,24 +1,57 @@
use std::fmt::Debug;
use std::net::SocketAddr;
use std::sync::atomic::AtomicBool;
use std::sync::Arc;
use crate::common::error::Error;
use anyhow::Context;
use hickory_net::runtime::TokioRuntimeProvider;
use hickory_proto::rr::rdata::SRV;
use hickory_proto::rr::{IntoName, RData};
use hickory_proto::rr::{IntoName, LowerName, RData};
use hickory_resolver::config::{
ConnectionConfig, LookupIpStrategy, NameServerConfig, ResolverConfig, ResolverOpts,
};
use hickory_resolver::system_conf::read_system_conf;
use hickory_resolver::{Resolver, TokioResolver};
use idna::AsciiDenyList;
use once_cell::sync::Lazy;
use std::net::SocketAddr;
use std::sync::Arc;
use std::sync::atomic::AtomicBool;
use tokio::net::lookup_host;
use crate::common::error::Error;
pub fn sanitize(name: impl AsRef<str>) -> String {
let name = name.as_ref();
let dot = name.ends_with('.');
let mut name = idna::domain_to_ascii_cow(name.as_ref(), AsciiDenyList::EMPTY)
.unwrap_or_default()
.into_owned()
.to_lowercase()
.split('.')
.map(|label| {
label
.chars()
.map(|c| if c.is_ascii_alphanumeric() { c } else { '-' })
.take(63)
.collect::<String>()
.trim_matches('-')
.to_string()
})
.filter(|label| !label.is_empty())
.collect::<Vec<_>>()
.join(".");
name.truncate(253);
if dot {
name.push('.');
}
name
}
pub fn parse(name: impl AsRef<str>) -> LowerName {
let name = name.as_ref();
if let Ok(name) = name.parse() {
name
} else {
let sanitized = sanitize(name);
tracing::debug!("invalid name: {}, sanitized to: {}", name, sanitized);
sanitized.parse().unwrap_or_default()
}
}
pub fn resolver_conf() -> (ResolverConfig, ResolverOpts) {
let mut config = ResolverConfig::default();
@@ -161,6 +194,31 @@ mod tests {
use super::*;
#[test]
fn parse_matrix_cases() {
let cases = [
["Example.COM.", "example.com."],
["a_b!.et.net.", "a-b.et.net."],
["foo..bar.com.", "foo.bar.com."],
[
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com.",
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com.",
],
["___", "___"],
["!", ""],
["", ""],
];
for [input, expected] in cases {
let parsed = parse(input);
let expected: LowerName = expected.parse().unwrap();
assert_eq!(
parsed, expected,
"parse({input:?}) should equal {expected:?}, got {parsed:?}"
);
}
}
#[tokio::test]
async fn test_socket_addrs() {
let url = url::Url::parse("tcp://github-ci-test.easytier.cn:80").unwrap();