Built a proxy crate, looking for suggestions

Hello the great community,

I was developing a CLI program and needed a crate that handles all kinds of proxy servers, and was surprised to realize that there was no such crate, so I decided to do it myself. After some commits in my free time, I think I've come to a version that looks usable. Since I'm pretty new to Rust, I decide to come here to look for suggestions for future improvement.

So here it is: GitHub docs.rs. The crate name is proxie.

I haven't written any docs yet, so I'm putting the basic usage here:

use tokio::{io::{AsyncWriteExt, BufReader, AsyncBufReadExt}};
use futures::future;
use proxie::{SOCKS5Proxy, tokio::AsyncProxy};

#[tokio::main]
async fn main() {
    let n_thread = 10;
    let mut handles = vec![];

    for _ in 0..n_thread {
        handles.push(tokio::spawn(async {
            let request = format!("GET / HTTP/1.1\r\n\r\n");

            let server = SOCKS5Proxy::new("127.0.0.1", 1080, None);
            let mut stream = server.connect("example.com:80").await.unwrap();

            //let mut stream = TcpStream::connect("example.com:80").await.unwrap();
            stream.write_all(request.as_bytes()).await.unwrap();
            stream.flush().await.unwrap();

            let mut reader = BufReader::new(&mut stream);
            let mut buffer = String::new();

            loop {
                reader.read_line(&mut buffer).await.unwrap();

                if buffer.ends_with("\r\n\r\n") {
                    break;
                }
            }

            print!("{}", buffer);
        }));
    }

    future::join_all(handles).await;
}

Or if with username/password authentication:

...
use proxie::{SOCKS5Proxy, tokio::AsyncProxy, Auth};
...
let server = SOCKS5Proxy::new("127.0.0.1", 1080, Auth::new("user", "pass"));
...

This is the example of sending a basic HTTP request through a SOCKS5 proxy server, using Tokio. For HTTP proxy the usage is exactly the same. There is also support for async-std and synchronous std::net, with similar API. The async runtime to use (or just synchronous) is configured via Cargo.toml:

proxie = { version = "0.0.2", features = ["enable_tokio"] }
//Available features: "enable_tokio", "enable_async_std" and "enable_sync".

In addition to the work I've done, here's what I'm planning:

  • Docs
  • UDP support for SOCKS5
  • HTTPS proxy and SOCKS4a support (low priority due to low popularity)
  • Implementing every (trait) method available on each TcpStream to my ProxyTcpStream (will just forwarding to the real TcpStream's methods be sufficient?)
  • Unit tests

But my main concern now is the user API: does the current API looks reasonable? It would be good to stabilize the API before making the first actual release, and I'll refrain from touching the API afterward.

That's everything I have for now. I would highly appreciate every suggestion, and I'll be glad if anyone looking for such a crate can try my work. Thanks!

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.