mirror of
https://ghfast.top/https://github.com/StarCitizenToolBox/app.git
synced 2025-06-28 12:34:45 +08:00
Init
This commit is contained in:
@ -12,18 +12,8 @@ crate-type = ["cdylib", "staticlib"]
|
||||
|
||||
[dependencies]
|
||||
flutter_rust_bridge = "=2.3.0"
|
||||
tokio = { version = "1", features = ["rt", "rt-multi-thread", "macros", "process"] }
|
||||
futures = { version = "0.3", default-features = false, features = ["executor"] }
|
||||
url = "2.5"
|
||||
once_cell = "1.19"
|
||||
reqwest = { version = "0.12", features = ["rustls-tls-webpki-roots", "cookies", "gzip", "json", "stream"] }
|
||||
hickory-resolver = { version = "0.24" }
|
||||
reqwest = { version = "0.12", features = ["json", "stream"] }
|
||||
anyhow = "1.0"
|
||||
|
||||
scopeguard = "1.2"
|
||||
notify-rust = "4"
|
||||
asar = "0.3.0"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
windows = { version = "0.58.0", features = ["Win32_UI_WindowsAndMessaging"] }
|
||||
win32job = "2"
|
||||
|
@ -1,52 +0,0 @@
|
||||
use std::fs::File;
|
||||
|
||||
use asar::{AsarReader, AsarWriter};
|
||||
use tokio::fs;
|
||||
|
||||
pub struct RsiLauncherAsarData {
|
||||
pub asar_path: String,
|
||||
pub main_js_path: String,
|
||||
pub main_js_content: Vec<u8>,
|
||||
}
|
||||
|
||||
impl RsiLauncherAsarData {
|
||||
pub async fn write_main_js(&self, content: Vec<u8>) -> anyhow::Result<()> {
|
||||
let mut asar_writer = AsarWriter::new();
|
||||
let asar_mem_file = fs::read(self.asar_path.clone()).await?;
|
||||
let asar = AsarReader::new(&asar_mem_file, None)?;
|
||||
asar.files().iter().for_each(|v| {
|
||||
let (path, file) = v;
|
||||
let path_string = path.clone().into_os_string().into_string().unwrap();
|
||||
if path_string == self.main_js_path {
|
||||
asar_writer.write_file(path, &content, true).unwrap();
|
||||
} else {
|
||||
asar_writer.write_file(path, file.data(), true).unwrap();
|
||||
}
|
||||
});
|
||||
// rm old asar
|
||||
fs::remove_file(&self.asar_path).await?;
|
||||
// write new asar
|
||||
asar_writer.finalize(File::create(&self.asar_path)?)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_rsi_launcher_asar_data(asar_path: &str) -> anyhow::Result<RsiLauncherAsarData> {
|
||||
let asar_mem_file = fs::read(asar_path).await?;
|
||||
let asar = AsarReader::new(&asar_mem_file, None)?;
|
||||
let mut main_js_path = String::from("");
|
||||
let mut main_js_content: Vec<u8> = Vec::new();
|
||||
asar.files().iter().for_each(|v| {
|
||||
let (path, file) = v;
|
||||
let path_string = path.clone().into_os_string().into_string().unwrap();
|
||||
if path_string.starts_with("app\\static\\js\\main.") && path_string.ends_with(".js") {
|
||||
main_js_path = path_string;
|
||||
main_js_content = file.data().to_vec();
|
||||
}
|
||||
});
|
||||
Ok(RsiLauncherAsarData {
|
||||
asar_path: asar_path.to_string(),
|
||||
main_js_path,
|
||||
main_js_content,
|
||||
})
|
||||
}
|
@ -16,7 +16,7 @@ pub enum MyMethod {
|
||||
}
|
||||
|
||||
fn _my_method_to_hyper_method(m: MyMethod) -> Method {
|
||||
return match m {
|
||||
match m {
|
||||
MyMethod::Options => Method::OPTIONS,
|
||||
MyMethod::Gets => Method::GET,
|
||||
MyMethod::Post => Method::POST,
|
||||
@ -26,7 +26,7 @@ fn _my_method_to_hyper_method(m: MyMethod) -> Method {
|
||||
MyMethod::Trace => Method::TRACE,
|
||||
MyMethod::Connect => Method::CONNECT,
|
||||
MyMethod::Patch => Method::PATCH,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_default_header(headers: HashMap<String, String>) {
|
||||
@ -38,22 +38,12 @@ pub async fn fetch(
|
||||
url: String,
|
||||
headers: Option<HashMap<String, String>>,
|
||||
input_data: Option<Vec<u8>>,
|
||||
with_ip_address: Option<String>,
|
||||
) -> anyhow::Result<RustHttpResponse> {
|
||||
http_package::fetch(
|
||||
_my_method_to_hyper_method(method),
|
||||
url,
|
||||
headers,
|
||||
input_data,
|
||||
with_ip_address,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn dns_lookup_txt(host: String) -> anyhow::Result<Vec<String>> {
|
||||
http_package::dns_lookup_txt(host).await
|
||||
}
|
||||
|
||||
pub async fn dns_lookup_ips(host: String) -> anyhow::Result<Vec<String>> {
|
||||
http_package::dns_lookup_ips(host).await
|
||||
.await
|
||||
}
|
||||
|
@ -2,6 +2,3 @@
|
||||
// Do not put code in `mod.rs`, but put in e.g. `simple.rs`.
|
||||
//
|
||||
pub mod http_api;
|
||||
pub mod rs_process;
|
||||
pub mod win32_api;
|
||||
pub mod asar_api;
|
||||
|
@ -1,180 +0,0 @@
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use flutter_rust_bridge::frb;
|
||||
use futures::executor::block_on;
|
||||
use once_cell::sync::Lazy;
|
||||
use scopeguard::defer;
|
||||
use tokio::io::AsyncBufReadExt;
|
||||
use tokio::io::AsyncWriteExt;
|
||||
use tokio::io::BufReader;
|
||||
use tokio::process::ChildStdin;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use crate::frb_generated::StreamSink;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum RsProcessStreamDataType {
|
||||
Output,
|
||||
Error,
|
||||
Exit,
|
||||
}
|
||||
|
||||
pub struct RsProcessStreamData {
|
||||
pub data_type: RsProcessStreamDataType,
|
||||
pub data: String,
|
||||
pub rs_pid: u32,
|
||||
}
|
||||
|
||||
#[frb(non_opaque)]
|
||||
pub struct RsProcess {
|
||||
pub child_stdin: ChildStdin,
|
||||
pub rs_pid: u32,
|
||||
}
|
||||
|
||||
static RS_PROCESS_MAP: Lazy<Mutex<HashMap<u32, RsProcess>>> = Lazy::new(|| Mutex::new(HashMap::new()));
|
||||
|
||||
pub async fn start(
|
||||
executable: &str,
|
||||
arguments: Vec<String>,
|
||||
working_directory: &str,
|
||||
stream_sink: StreamSink<RsProcessStreamData>,
|
||||
) {
|
||||
let stream_sink_arc = Arc::from(stream_sink);
|
||||
let mut command = tokio::process::Command::new(executable);
|
||||
command
|
||||
.args(arguments)
|
||||
.current_dir(working_directory)
|
||||
.stdin(std::process::Stdio::piped())
|
||||
.stdout(std::process::Stdio::piped())
|
||||
.stderr(std::process::Stdio::piped())
|
||||
.kill_on_drop(true);
|
||||
#[cfg(target_os = "windows")]
|
||||
command.creation_flags(0x08000000);
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
let job = win32job::Job::create().unwrap();
|
||||
#[cfg(target_os = "windows")]
|
||||
let mut info = job.query_extended_limit_info().unwrap();
|
||||
#[cfg(target_os = "windows")]
|
||||
info.limit_kill_on_job_close();
|
||||
#[cfg(target_os = "windows")]
|
||||
job.set_extended_limit_info(&mut info).unwrap();
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
let job_arc = Arc::from(job);
|
||||
|
||||
if let Ok(mut child) = command.spawn() {
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
let raw_handle = child.raw_handle();
|
||||
if raw_handle.is_some() {
|
||||
job_arc
|
||||
.assign_process(raw_handle.unwrap() as isize)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
let stdin = child
|
||||
.stdin
|
||||
.take()
|
||||
.expect("[rs_process] Failed to open stdin");
|
||||
let pid = child.id().expect("[rs_process] Failed to get pid");
|
||||
{
|
||||
let mut map = RS_PROCESS_MAP.lock().await;
|
||||
map.insert(
|
||||
pid,
|
||||
RsProcess {
|
||||
child_stdin: stdin,
|
||||
rs_pid: pid,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
defer! {
|
||||
let mut map = block_on(RS_PROCESS_MAP.lock());
|
||||
map.remove(&pid);
|
||||
println!("RS_PROCESS_MAP ..defer ..len() = {}", map.len());
|
||||
}
|
||||
|
||||
let stdout = child
|
||||
.stdout
|
||||
.take()
|
||||
.expect("[rs_process] Failed to open stdout");
|
||||
let stderr = child
|
||||
.stderr
|
||||
.take()
|
||||
.expect("[rs_process] Failed to open stderr");
|
||||
|
||||
let output_task = tokio::spawn(_process_output(
|
||||
stdout,
|
||||
stream_sink_arc.clone(),
|
||||
RsProcessStreamDataType::Output,
|
||||
pid,
|
||||
));
|
||||
let error_task = tokio::spawn(_process_output(
|
||||
stderr,
|
||||
stream_sink_arc.clone(),
|
||||
RsProcessStreamDataType::Error,
|
||||
pid,
|
||||
));
|
||||
|
||||
tokio::select! {_ = output_task => (), _ = error_task => () }
|
||||
|
||||
let exit_status = child
|
||||
.wait()
|
||||
.await
|
||||
.expect("[rs_process] Failed to wait for child process");
|
||||
|
||||
if !exit_status.success() {
|
||||
println!(
|
||||
"[rs_process] Child process exited with an error: {:?}",
|
||||
exit_status
|
||||
);
|
||||
let message = RsProcessStreamData {
|
||||
data_type: RsProcessStreamDataType::Exit,
|
||||
data: "exit".to_string(),
|
||||
rs_pid: pid,
|
||||
};
|
||||
stream_sink_arc.add(message).unwrap();
|
||||
}
|
||||
} else {
|
||||
println!("Failed to start");
|
||||
let message = RsProcessStreamData {
|
||||
data_type: RsProcessStreamDataType::Error,
|
||||
data: "Failed to start".to_string(),
|
||||
rs_pid: 0,
|
||||
};
|
||||
stream_sink_arc.add(message).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub async fn write(rs_pid: &u32, data: String) {
|
||||
let mut map = RS_PROCESS_MAP.lock().await;
|
||||
let process = map.get_mut(rs_pid).unwrap();
|
||||
process
|
||||
.child_stdin
|
||||
.write_all(data.as_bytes())
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
async fn _process_output<R>(
|
||||
stdout: R,
|
||||
stream_sink: Arc<StreamSink<RsProcessStreamData>>,
|
||||
data_type: RsProcessStreamDataType,
|
||||
pid: u32,
|
||||
) where
|
||||
R: tokio::io::AsyncRead + Unpin,
|
||||
{
|
||||
let reader = BufReader::new(stdout);
|
||||
let mut lines = reader.lines();
|
||||
|
||||
while let Some(line) = lines.next_line().await.unwrap() {
|
||||
let message = RsProcessStreamData {
|
||||
data_type,
|
||||
data: line.trim().parse().unwrap(),
|
||||
rs_pid: pid,
|
||||
};
|
||||
stream_sink.add(message).unwrap();
|
||||
}
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
use notify_rust::Notification;
|
||||
|
||||
pub fn send_notify(
|
||||
summary: Option<String>,
|
||||
body: Option<String>,
|
||||
app_name: Option<String>,
|
||||
app_id: Option<String>,
|
||||
) -> anyhow::Result<()> {
|
||||
let mut n = Notification::new();
|
||||
if let Some(summary) = summary {
|
||||
n.summary(&summary);
|
||||
}
|
||||
if let Some(body) = body {
|
||||
n.body(&body);
|
||||
}
|
||||
if let Some(app_name) = app_name {
|
||||
n.appname(&app_name);
|
||||
}
|
||||
#[cfg(target_os = "windows")]
|
||||
if let Some(app_id) = app_id {
|
||||
n.app_id(&app_id);
|
||||
}
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
println!("send_notify (unix) appid: {:?}", app_id);
|
||||
n.show()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
pub fn set_foreground_window(window_name: &str) -> anyhow::Result<bool> {
|
||||
use windows::core::{HSTRING, PCWSTR};
|
||||
use windows::Win32::Foundation::HWND;
|
||||
use windows::Win32::UI::WindowsAndMessaging;
|
||||
let window_name_p: PCWSTR = PCWSTR(HSTRING::from(window_name).as_ptr());
|
||||
let h = unsafe { WindowsAndMessaging::FindWindowW(PCWSTR::null(), window_name_p)? };
|
||||
if h == HWND::default() {
|
||||
return Ok(false);
|
||||
}
|
||||
let sr = unsafe { WindowsAndMessaging::ShowWindow(h, WindowsAndMessaging::SW_RESTORE) };
|
||||
if !sr.as_bool() {
|
||||
return Ok(false);
|
||||
}
|
||||
let r = unsafe { WindowsAndMessaging::SetForegroundWindow(h) };
|
||||
Ok(r.as_bool())
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
pub fn set_foreground_window(window_name: &str) -> anyhow::Result<bool> {
|
||||
println!("set_foreground_window (unix): {}", window_name);
|
||||
return Ok(false);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,98 +0,0 @@
|
||||
use hickory_resolver::config::{NameServerConfigGroup, ResolverConfig, ResolverOpts};
|
||||
use hickory_resolver::{lookup_ip::LookupIpIntoIter, TokioAsyncResolver};
|
||||
use once_cell::sync::{Lazy, OnceCell};
|
||||
use reqwest::dns::{Addrs, Name, Resolve, Resolving};
|
||||
use std::collections::HashMap;
|
||||
use std::io;
|
||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
pub static MY_HOSTS_MAP: Lazy<RwLock<HashMap<String, IpAddr>>> =
|
||||
Lazy::new(|| RwLock::from(HashMap::new()));
|
||||
|
||||
/// 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 my_hosts = MY_HOSTS_MAP.read().unwrap();
|
||||
let name_str = name.as_str();
|
||||
if let Some(ip) = my_hosts.get(name_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)?;
|
||||
let lookup = resolver.lookup_ip(name.as_str()).await?;
|
||||
let addrs: Addrs = Box::new(SocketAddrs {
|
||||
iter: lookup.into_iter(),
|
||||
});
|
||||
Ok(addrs)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
.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 {
|
||||
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 group = NameServerConfigGroup::from_ips_clear(
|
||||
&[
|
||||
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)),
|
||||
],
|
||||
53,
|
||||
false,
|
||||
);
|
||||
let cfg = ResolverConfig::from_parts(None, vec![], group);
|
||||
let mut opts = ResolverOpts::default();
|
||||
opts.edns0 = true;
|
||||
opts.timeout = std::time::Duration::from_secs(5);
|
||||
opts.try_tcp_on_error = true;
|
||||
opts.ip_strategy = hickory_resolver::config::LookupIpStrategy::Ipv4thenIpv6;
|
||||
opts.num_concurrent_reqs = 3;
|
||||
Ok(TokioAsyncResolver::tokio(cfg, opts))
|
||||
}
|
@ -1,25 +1,10 @@
|
||||
pub mod dns;
|
||||
|
||||
use once_cell::sync::Lazy;
|
||||
use reqwest::header::{HeaderMap, HeaderName, HeaderValue};
|
||||
use reqwest::{Method, RequestBuilder};
|
||||
use scopeguard::defer;
|
||||
use std::collections::HashMap;
|
||||
use std::str::FromStr;
|
||||
use std::sync::{Arc, RwLock};
|
||||
use std::time::Duration;
|
||||
use url::Url;
|
||||
use std::sync::RwLock;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub enum MyHttpVersion {
|
||||
HTTP_09,
|
||||
HTTP_10,
|
||||
HTTP_11,
|
||||
HTTP_2,
|
||||
HTTP_3,
|
||||
HTTP_UNKNOWN,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct RustHttpResponse {
|
||||
@ -27,41 +12,15 @@ pub struct RustHttpResponse {
|
||||
pub headers: HashMap<String, String>,
|
||||
pub url: String,
|
||||
pub content_length: Option<u64>,
|
||||
pub version: MyHttpVersion,
|
||||
pub remote_addr: String,
|
||||
pub data: Option<Vec<u8>>,
|
||||
}
|
||||
|
||||
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,
|
||||
_ => MyHttpVersion::HTTP_UNKNOWN,
|
||||
}
|
||||
}
|
||||
|
||||
static DEFAULT_HEADER: Lazy<RwLock<HeaderMap>> = Lazy::new(|| RwLock::from(HeaderMap::new()));
|
||||
|
||||
static DNS_CLIENT: Lazy<Arc<dns::MyHickoryDnsResolver>> =
|
||||
Lazy::new(|| Arc::from(dns::MyHickoryDnsResolver::default()));
|
||||
static HTTP_CLIENT: Lazy<reqwest::Client> = Lazy::new(|| new_http_client());
|
||||
|
||||
static HTTP_CLIENT: Lazy<reqwest::Client> = Lazy::new(|| 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));
|
||||
}
|
||||
fn new_http_client() -> reqwest::Client {
|
||||
let c = reqwest::Client::builder();
|
||||
c.build().unwrap()
|
||||
}
|
||||
|
||||
@ -81,34 +40,10 @@ 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 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 = Url::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)
|
||||
};
|
||||
let mut req = _mix_header(HTTP_CLIENT.request(method, url_clone), headers);
|
||||
if input_data.is_some() {
|
||||
req = req.body(input_data.unwrap());
|
||||
}
|
||||
@ -117,40 +52,23 @@ pub async fn fetch(
|
||||
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());
|
||||
data = Some(bytes?.to_vec());
|
||||
}
|
||||
|
||||
let version = _hyper_version_to_my_version(version);
|
||||
|
||||
let resp = RustHttpResponse {
|
||||
status_code,
|
||||
headers: resp_headers,
|
||||
url,
|
||||
content_length,
|
||||
version,
|
||||
remote_addr,
|
||||
data,
|
||||
};
|
||||
Ok(resp)
|
||||
}
|
||||
|
||||
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