mirror of
https://ghfast.top/https://github.com/StarCitizenToolBox/app.git
synced 2025-07-28 18:53:59 +08:00
feat: [RustHTTP] DNS Host Map
This commit is contained in:
@ -1,11 +1,17 @@
|
||||
use std::io;
|
||||
use hickory_resolver::config::{NameServerConfigGroup, ResolverConfig, ResolverOpts};
|
||||
use hickory_resolver::{lookup_ip::LookupIpIntoIter, TokioAsyncResolver};
|
||||
use hyper::client::connect::dns::Name;
|
||||
use once_cell::sync::OnceCell;
|
||||
use reqwest::dns::{Addrs, Resolve, Resolving};
|
||||
use std::collections::HashMap;
|
||||
use std::io;
|
||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||
use std::sync::Arc;
|
||||
use hickory_resolver::config::{NameServerConfigGroup, ResolverConfig, ResolverOpts};
|
||||
use std::sync::{Arc, RwLock};
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref MY_HOSTS_MAP: RwLock<HashMap<String, IpAddr>> = RwLock::from(HashMap::new());
|
||||
}
|
||||
|
||||
/// Wrapper around an `AsyncResolver`, which implements the `Resolve` trait.
|
||||
#[derive(Debug, Default, Clone)]
|
||||
@ -22,6 +28,14 @@ struct SocketAddrs {
|
||||
|
||||
impl Resolve for MyHickoryDnsResolver {
|
||||
fn resolve(&self, name: Name) -> Resolving {
|
||||
let my_hosts = MY_HOSTS_MAP.read().unwrap();
|
||||
let name_str = name.to_string();
|
||||
if let Some(ip) = my_hosts.get(name_str.as_str()) {
|
||||
let addrs: Addrs = Box::new(std::iter::once(SocketAddr::new(*ip, 0)));
|
||||
println!("using host map === {:?}", name_str);
|
||||
return Box::pin(async move { Ok(addrs) });
|
||||
}
|
||||
|
||||
let resolver = self.clone();
|
||||
Box::pin(async move {
|
||||
let resolver = resolver.state.get_or_try_init(new_resolver)?;
|
||||
@ -38,11 +52,21 @@ impl MyHickoryDnsResolver {
|
||||
pub(crate) async fn lookup_txt(&self, name: String) -> anyhow::Result<Vec<String>> {
|
||||
let resolver = self.state.get_or_try_init(new_resolver)?;
|
||||
let txt = resolver.txt_lookup(name).await?;
|
||||
let t = txt.iter()
|
||||
let t = txt
|
||||
.iter()
|
||||
.map(|rdata| rdata.to_string())
|
||||
.collect::<Vec<_>>();
|
||||
Ok(t)
|
||||
}
|
||||
pub(crate) async fn lookup_ips(&self, name: String) -> anyhow::Result<Vec<String>> {
|
||||
let resolver = self.state.get_or_try_init(new_resolver)?;
|
||||
let ips = resolver.ipv4_lookup(name).await?;
|
||||
let t = ips
|
||||
.iter()
|
||||
.map(|ip| ip.to_string())
|
||||
.collect::<Vec<_>>();
|
||||
Ok(t)
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for SocketAddrs {
|
||||
@ -58,14 +82,15 @@ fn new_resolver() -> io::Result<TokioAsyncResolver> {
|
||||
&[
|
||||
IpAddr::V4(Ipv4Addr::new(119, 29, 29, 29)),
|
||||
IpAddr::V4(Ipv4Addr::new(223, 6, 6, 6)),
|
||||
IpAddr::V4(Ipv4Addr::new(1, 1, 1, 1)),
|
||||
IpAddr::V4(Ipv4Addr::new(8, 8, 8, 8)),
|
||||
IpAddr::V4(Ipv4Addr::new(180, 76, 76, 76)),
|
||||
IpAddr::V4(Ipv4Addr::new(1, 2, 4, 8)),
|
||||
IpAddr::V4(Ipv4Addr::new(166, 111, 8, 28)),
|
||||
IpAddr::V4(Ipv4Addr::new(101, 226, 4, 6)),
|
||||
IpAddr::V4(Ipv4Addr::new(114, 114, 114, 114)),
|
||||
IpAddr::V4(Ipv4Addr::new(8, 8, 8, 8)),
|
||||
IpAddr::V4(Ipv4Addr::new(1, 1, 1, 1)),
|
||||
], 53, true);
|
||||
], 53, true,
|
||||
);
|
||||
let cfg = ResolverConfig::from_parts(None, vec![], group);
|
||||
let mut opts = ResolverOpts::default();
|
||||
opts.edns0 = true;
|
||||
|
@ -1,16 +1,27 @@
|
||||
pub mod dns;
|
||||
|
||||
use scopeguard::defer;
|
||||
use lazy_static::lazy_static;
|
||||
use hyper::Uri;
|
||||
use reqwest::header::{HeaderMap, HeaderName, HeaderValue};
|
||||
use reqwest::{Method, RequestBuilder};
|
||||
use std::collections::HashMap;
|
||||
use std::str::FromStr;
|
||||
use std::sync::{Arc, RwLock};
|
||||
use std::time::Duration;
|
||||
use flutter_rust_bridge::for_generated::lazy_static;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub enum MyHttpVersion { HTTP_09, HTTP_10, HTTP_11, HTTP_2, HTTP_3 }
|
||||
pub enum MyHttpVersion {
|
||||
HTTP_09,
|
||||
HTTP_10,
|
||||
HTTP_11,
|
||||
HTTP_2,
|
||||
HTTP_3,
|
||||
HTTP_UNKNOWN,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct RustHttpResponse {
|
||||
pub status_code: u16,
|
||||
pub headers: HashMap<String, String>,
|
||||
@ -23,28 +34,34 @@ pub struct RustHttpResponse {
|
||||
|
||||
fn _hyper_version_to_my_version(v: reqwest::Version) -> MyHttpVersion {
|
||||
match v {
|
||||
reqwest::Version::HTTP_09 => { MyHttpVersion::HTTP_09 }
|
||||
reqwest::Version::HTTP_10 => { MyHttpVersion::HTTP_10 }
|
||||
reqwest::Version::HTTP_11 => { MyHttpVersion::HTTP_11 }
|
||||
reqwest::Version::HTTP_2 => { MyHttpVersion::HTTP_2 }
|
||||
reqwest::Version::HTTP_3 => { MyHttpVersion::HTTP_3 }
|
||||
_ => { panic!("Unsupported HTTP version") }
|
||||
reqwest::Version::HTTP_09 => MyHttpVersion::HTTP_09,
|
||||
reqwest::Version::HTTP_10 => MyHttpVersion::HTTP_10,
|
||||
reqwest::Version::HTTP_11 => MyHttpVersion::HTTP_11,
|
||||
reqwest::Version::HTTP_2 => MyHttpVersion::HTTP_2,
|
||||
reqwest::Version::HTTP_3 => MyHttpVersion::HTTP_3,
|
||||
_ => MyHttpVersion::HTTP_UNKNOWN,
|
||||
}
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref DEFAULT_HEADER: RwLock<HeaderMap> = RwLock::from(HeaderMap::new());
|
||||
static ref DNS_CLIENT : Arc<dns::MyHickoryDnsResolver> = Arc::from(dns::MyHickoryDnsResolver::default());
|
||||
static ref HTTP_CLIENT: reqwest::Client = {
|
||||
reqwest::Client::builder()
|
||||
.dns_resolver(DNS_CLIENT.clone())
|
||||
.use_rustls_tls()
|
||||
.connect_timeout(Duration::from_secs(10))
|
||||
.gzip(true)
|
||||
.no_proxy()
|
||||
.build()
|
||||
.unwrap()
|
||||
};
|
||||
static ref DNS_CLIENT: Arc<dns::MyHickoryDnsResolver> = Arc::from(dns::MyHickoryDnsResolver::default());
|
||||
static ref HTTP_CLIENT: reqwest::Client = new_http_client(true);
|
||||
}
|
||||
|
||||
fn new_http_client(keep_alive: bool) -> reqwest::Client {
|
||||
let mut c = reqwest::Client::builder()
|
||||
.dns_resolver(DNS_CLIENT.clone())
|
||||
.use_rustls_tls()
|
||||
.connect_timeout(Duration::from_secs(10))
|
||||
.gzip(true)
|
||||
.no_proxy();
|
||||
if !keep_alive {
|
||||
c = c.tcp_keepalive(None);
|
||||
} else {
|
||||
c = c.tcp_keepalive(Duration::from_secs(120));
|
||||
}
|
||||
c.build().unwrap()
|
||||
}
|
||||
|
||||
pub fn set_default_header(headers: HashMap<String, String>) {
|
||||
@ -63,13 +80,34 @@ pub async fn fetch(
|
||||
url: String,
|
||||
headers: Option<HashMap<String, String>>,
|
||||
input_data: Option<Vec<u8>>,
|
||||
with_ip_address: Option<String>,
|
||||
) -> anyhow::Result<RustHttpResponse> {
|
||||
let mut req = _mix_header(HTTP_CLIENT.request(method, url), headers);
|
||||
let address_clone = with_ip_address.clone();
|
||||
let url_clone = url.clone();
|
||||
|
||||
if address_clone.is_some() {
|
||||
let addr = std::net::IpAddr::from_str(with_ip_address.unwrap().as_str()).unwrap();
|
||||
let mut hosts = dns::MY_HOSTS_MAP.write().unwrap();
|
||||
let url_host = Uri::from_str(url.as_str()).unwrap().host().unwrap().to_string();
|
||||
hosts.insert(url_host, addr);
|
||||
}
|
||||
|
||||
defer! {
|
||||
if address_clone.is_some() {
|
||||
let mut hosts = dns::MY_HOSTS_MAP.write().unwrap();
|
||||
hosts.remove(url.clone().as_str());
|
||||
}
|
||||
}
|
||||
|
||||
let mut req = if address_clone.is_some() {
|
||||
_mix_header(new_http_client(false).request(method, url_clone), headers)
|
||||
} else {
|
||||
_mix_header(HTTP_CLIENT.request(method, url_clone), headers)
|
||||
};
|
||||
if input_data.is_some() {
|
||||
req = req.body(input_data.unwrap());
|
||||
}
|
||||
let resp = req.send().await?;
|
||||
|
||||
let url = resp.url().to_string();
|
||||
let status_code = resp.status().as_u16();
|
||||
let resp_headers = _reade_resp_header(resp.headers());
|
||||
@ -104,6 +142,10 @@ pub async fn dns_lookup_txt(name: String) -> anyhow::Result<Vec<String>> {
|
||||
DNS_CLIENT.lookup_txt(name).await
|
||||
}
|
||||
|
||||
pub async fn dns_lookup_ips(name: String) -> anyhow::Result<Vec<String>> {
|
||||
DNS_CLIENT.lookup_ips(name).await
|
||||
}
|
||||
|
||||
fn _reade_resp_header(r_header: &HeaderMap) -> HashMap<String, String> {
|
||||
let mut resp_headers = HashMap::new();
|
||||
for ele in r_header {
|
||||
|
Reference in New Issue
Block a user