Repository navigation
Expand file tree
/
Copy pathproxy_test.rs
More file actions
103 lines (91 loc) · 3.4 KB
/
Copy pathproxy_test.rs
File metadata and controls
103 lines (91 loc) · 3.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
//! Live proxy verification — proves the lib actually routes through HTTP / SOCKS5 proxies.
//!
//! Run: `cargo run --example proxy_test -- <panel-host> <panel-port> <user> <pass> <proxy-url>`
//!
//! Proxy-url examples:
//! http://127.0.0.1:18888
//! socks5://127.0.0.1:11080
//! socks5://user:pass@127.0.0.1:11080
//!
//! Tip on macOS: panels reachable on host's `127.0.0.1` are *not* reachable from
//! within proxy containers. Use `host.docker.internal` as the panel host
//! when the proxy is running in Docker.
use threexui_rs::{Client, ClientConfig, Error};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let args: Vec<String> = std::env::args().collect();
let host = args
.get(1)
.cloned()
.unwrap_or_else(|| "host.docker.internal".into());
let port: u16 = args.get(2).and_then(|p| p.parse().ok()).unwrap_or(8787);
let user = args.get(3).cloned().unwrap_or_else(|| "admin".into());
let pass = args.get(4).cloned().unwrap_or_else(|| "admin".into());
let proxy = args
.get(5)
.cloned()
.unwrap_or_else(|| "http://127.0.0.1:18888".into());
println!("\n========================================================");
println!(" PROXY TEST panel=http://{host}:{port} via {proxy}");
println!("========================================================\n");
// 1. Bad-URL validation surfaces as Config error
let bad = ClientConfig::builder()
.host(host.clone())
.port(port)
.proxy("not a url")
.build();
match bad {
Err(Error::Config(msg)) if msg.contains("invalid proxy url") => {
println!(" ✓ invalid-url validation: {msg}")
}
other => {
println!(
" ✗ invalid-url validation expected Config error, got {:?}",
other.is_ok()
);
std::process::exit(1);
}
}
// 2. Unreachable proxy → connection error (proves proxy is being used)
let dead = Client::new(
ClientConfig::builder()
.host(host.clone())
.port(port)
.timeout_secs(3)
.proxy("http://127.0.0.1:1") // nothing listens on :1
.build()?,
);
match dead.login(&user, &pass).await {
Err(Error::Http(_)) => println!(" ✓ unreachable proxy → Http error (proxy is in path)"),
other => {
println!(
" ✗ expected Http error from dead proxy, got {:?}",
other.is_ok()
);
std::process::exit(1);
}
}
// 3. Working proxy → end-to-end calls succeed
let cfg = ClientConfig::builder()
.host(host.clone())
.port(port)
.timeout_secs(15)
.proxy(&proxy)
.build()?;
let client = Client::new(cfg);
client.login(&user, &pass).await?;
println!(" ✓ login via proxy");
let status = client.server().status().await?;
println!(
" ✓ server.status via proxy (cpu={:.1}% xray={})",
status.cpu, status.xray.state
);
let inbounds = client.inbounds().list().await?;
println!(" ✓ inbounds.list via proxy ({} inbounds)", inbounds.len());
let uuid = client.server().new_uuid().await?;
println!(" ✓ server.new_uuid via proxy ({})", uuid.uuid);
client.logout().await?;
println!(" ✓ logout via proxy");
println!("\n ALL PROXY CHECKS PASSED\n");
Ok(())
}