reqwest_ss_proxy 0.1.4

A reqwest middleware for proxying requests through Shadowsocks. / 一个用于 reqwest 的 Shadowsocks 代理中间件。
Documentation
use anyhow::Result;
use percent_encoding::percent_decode_str;
use regex::Regex;
use reqwest_middleware::{ClientBuilder, ClientWithMiddleware};
use reqwest_ss_proxy::{SsConnector, SsMiddleware};

fn hide_token_ss_url(url: &str) -> String {
  let re = Regex::new(r"ss://(.+)@").unwrap();
  let hidden_url = re.replace(url, "ss://*@").to_string();

  if let Some(hash_index) = hidden_url.find('#') {
    let base = &hidden_url[..hash_index];
    let fragment = &hidden_url[hash_index + 1..];
    if let Ok(decoded_fragment) = percent_decode_str(fragment).decode_utf8() {
      return format!("{}#{}", base, decoded_fragment);
    }
  }

  hidden_url
}

#[tokio::test]
async fn test_proxy_connection() -> Result<()> {
  let urls = match std::fs::read_to_string("tests/ss") {
    Ok(s) => s,
    Err(_) => {
      println!("未找到 tests/ss 文件,跳过代理连接测试
Could not find the tests/ss file, skipping proxy connection test");
      return Ok(());
    }
  };

  for url in urls.lines() {
    let url = url.trim();
    if url.is_empty() {
      continue;
    }
    println!("{}", hide_token_ss_url(url));

    // 1. Create the SsConnector.
    let connector = match SsConnector::new(url) {
      Ok(c) => c,
      Err(e) => {
        println!("{}", e);
        continue;
      }
    };

    // 2. Create the SsMiddleware from the connector.
    let ss_middleware = SsMiddleware::new(connector);

    // 3. Build the reqwest client with the middleware.
    let client = reqwest::Client::builder().build()?;
    let client: ClientWithMiddleware = ClientBuilder::new(client).with(ss_middleware).build();

    // 4. Send the request using the reqwest API.
    for test_url in ["http://ifconfig.me/ip", "https://ifconfig.me/ip"] {
      match client.get(test_url).send().await {
        Ok(res) => {
          let status = res.status();
          let ip = res.text().await?;
          println!("\t{test_url} {} {}", status, ip);
        }
        Err(e) => {
          println!("\t{test_url}{e}");
        }
      }
    }
  }

  Ok(())
}