#http-request #tor #request #sock #client

artiqwest

A simple client for making http request over Tor with Arti

11 releases

Uses new Rust 2024

new 0.1.18 Mar 25, 2025
0.1.15 Jan 16, 2025
0.1.13 Nov 20, 2024
0.1.11 Oct 17, 2024
0.1.5 Aug 20, 2024

#203 in HTTP client

Download history 266/week @ 2025-01-15 5/week @ 2025-01-29 31/week @ 2025-02-12 2/week @ 2025-02-19 40/week @ 2025-02-26 34/week @ 2025-03-19

74 downloads per month

MIT and LGPL-3.0-only

48KB
707 lines

logo

docs.rs Crates.io Total Downloads Crates.io License

Artiqwest is a simple HTTP client that routes *all (except localhost connects where it fallbacks to reqwest) requests through the Tor network using the arti_client and hyper. It provides two basic primitives: get and post, functions.

Artiqwest also provides a ws function to create a websocket connection to a hidden service using tokio-tungstenite. Currently websockets only work over tor and are untested over clearnet.

Example

use artiqwest::get;
use artiqwest::post;
use artiqwest::ws;
use futures_util::future;
use futures_util::pin_mut;
use futures_util::SinkExt;

 #[tokio::main]
 async fn main() {
        // Make a GET request to httpbin.org
        let response = get("https://httpbin.org/get").await.unwrap();
        assert_eq!(response.status(), 200);

        // Make a POST request to a hidden service
        let body = r#"{"test": "testing"}"#;
        let headers = vec![("Content-Type", "application/json")];
        let response = post("http://vpns6exmqmg5znqmgxa5c6rgzpt6imy5yzrbsoszovgfipdjypnchpyd.onion/echo", body, Some(headers)).await.unwrap();
        assert_eq!(response.to_string(), body);

        // Create a websocket connection to a hidden service.
        let (mut write, read) = ws("wss://ydrkehoqxt2q5atkmiyw7gmphvrmp6fkaufvt525cjr4hma3pb75nyid.onion/events").await.unwrap();
        let write_messages = {
		async {
			loop {
				write.send(Message::Text("Hello WebSocket".to_string())).await.unwrap();
				tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
			}
		}
	};

	let read_messages = {
		read.for_each(|message| async {
			let data = message.unwrap().into_data();
			let text = String::from_utf8(data).unwrap();
			println!("Received: {text}");
		})
	};

	pin_mut!(read_messages, write_messages);

	future::select(read_messages, write_messages).await;
 }

Dependencies

~80MB
~1.5M SLoC