update RSHttp

This commit is contained in:
2024-02-07 19:32:36 +08:00
parent 7e1352c0be
commit 5fa62351f2
19 changed files with 1202 additions and 169 deletions

View File

@ -0,0 +1,58 @@
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::io;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
use std::sync::Arc;
/// Wrapper around an `AsyncResolver`, which implements the `Resolve` trait.
#[derive(Debug, Default, Clone)]
pub(crate) struct MyHickoryDnsResolver {
/// Since we might not have been called in the context of a
/// Tokio Runtime in initialization, so we must delay the actual
/// construction of the resolver.
state: Arc<OnceCell<TokioAsyncResolver>>,
}
struct SocketAddrs {
iter: LookupIpIntoIter,
}
impl Resolve for MyHickoryDnsResolver {
fn resolve(&self, name: Name) -> Resolving {
let resolver = self.clone();
Box::pin(async move {
let resolver = resolver.state.get_or_try_init(new_resolver)?;
let lookup = resolver.lookup_ip(name.as_str()).await?;
let addrs: Addrs = Box::new(SocketAddrs {
iter: lookup.into_iter(),
});
Ok(addrs)
})
}
}
impl Iterator for SocketAddrs {
type Item = SocketAddr;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|ip_addr| SocketAddr::new(ip_addr, 0))
}
}
fn new_resolver() -> io::Result<TokioAsyncResolver> {
let ali_ips: &[IpAddr] = &[
IpAddr::V4(Ipv4Addr::new(223, 5, 5, 5)),
IpAddr::V4(Ipv4Addr::new(223, 6, 6, 6)),
IpAddr::V6("2400:3200::1".parse::<Ipv6Addr>().unwrap()),
IpAddr::V6("2400:3200:baba::1".parse::<Ipv6Addr>().unwrap()),
];
let group =
NameServerConfigGroup::from_ips_https(ali_ips, 443, "dns.alidns.com".to_string(), true);
let cfg = ResolverConfig::from_parts(None, vec![], group);
Ok(TokioAsyncResolver::tokio(cfg, ResolverOpts::default()))
}

View File

@ -0,0 +1,109 @@
pub mod dns;
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)]
pub struct RustHttpResponse {
pub status_code: u16,
pub headers: HashMap<String, String>,
pub url: String,
pub content_length: Option<u64>,
pub version: reqwest::Version,
pub remote_addr: String,
pub data: Option<Vec<u8>>,
}
lazy_static! {
static ref DEFAULT_HEADER: RwLock<HeaderMap> = RwLock::from(HeaderMap::new());
static ref HTTP_CLIENT: reqwest::Client = {
reqwest::Client::builder()
.use_rustls_tls()
.connect_timeout(Duration::from_secs(10))
.timeout(Duration::from_secs(10))
.dns_resolver(Arc::from(dns::MyHickoryDnsResolver::default()))
.build()
.unwrap()
};
}
pub fn set_default_header(headers: HashMap<String, String>) {
let mut dh = DEFAULT_HEADER.write().unwrap();
dh.clear();
for ele in headers {
dh.append(
HeaderName::from_str(ele.0.as_str()).unwrap(),
HeaderValue::from_str(ele.1.as_str()).unwrap(),
);
}
}
pub async fn fetch(
method: Method,
url: String,
headers: Option<HashMap<String, String>>,
input_data: Option<Vec<u8>>,
) -> reqwest::Result<RustHttpResponse> {
let mut req = _mix_header(HTTP_CLIENT.request(method, url), 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());
let content_length = resp.content_length();
let version = resp.version();
let mut remote_addr = "".to_string();
if resp.remote_addr().is_some() {
remote_addr = resp.remote_addr().unwrap().to_string();
}
let mut data: Option<Vec<u8>> = None;
let bytes = resp.bytes().await;
if bytes.is_ok() {
data = Some(bytes.unwrap().to_vec());
}
let resp = RustHttpResponse {
status_code,
headers: resp_headers,
url,
content_length,
version,
remote_addr,
data,
};
Ok(resp)
}
fn _reade_resp_header(r_header: &HeaderMap) -> HashMap<String, String> {
let mut resp_headers = HashMap::new();
for ele in r_header {
resp_headers.insert(
ele.0.as_str().to_string(),
ele.1.to_str().unwrap().to_string(),
);
}
resp_headers
}
fn _mix_header(
mut req: RequestBuilder,
headers: Option<HashMap<String, String>>,
) -> RequestBuilder {
if headers.is_some() {
for x in headers.unwrap() {
req = req.header(x.0, x.1);
}
}
let dh = DEFAULT_HEADER.read().unwrap();
req = req.headers(dh.clone());
req
}