Skip to content

Commit d60a6f3

Browse files
0x676e67Copilot
andauthored
feat(proxy): add Unix socket proxy support (#900)
* feat(connect): support `Unix` socket connection * add example * Update src/client/request.rs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 628e6b4 commit d60a6f3

19 files changed

Lines changed: 1022 additions & 508 deletions

File tree

Cargo.toml

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,11 @@ required-features = ["socks"]
241241
name = "form"
242242
path = "examples/form.rs"
243243

244+
[[example]]
245+
name = "connect_via_lower_priority_tokio_runtime"
246+
path = "examples/connect_via_lower_priority_tokio_runtime.rs"
247+
required-features = ["tracing"]
248+
244249
[[example]]
245250
name = "emulation_firefox"
246251
path = "examples/emulation_firefox.rs"
@@ -276,11 +281,6 @@ name = "request_with_emulation"
276281
path = "examples/request_with_emulation.rs"
277282
required-features = ["gzip", "brotli", "zstd", "deflate", "tracing"]
278283

279-
[[example]]
280-
name = "connect_via_lower_priority_tokio_runtime"
281-
path = "examples/connect_via_lower_priority_tokio_runtime.rs"
282-
required-features = ["tracing"]
283-
284284
[[example]]
285285
name = "request_with_local_address"
286286
path = "examples/request_with_local_address.rs"
@@ -304,3 +304,7 @@ required-features = ["ws", "futures-util/std", "tracing"]
304304
[[example]]
305305
name = "keylog"
306306
path = "examples/keylog.rs"
307+
308+
[[example]]
309+
name = "unix_socket"
310+
path = "examples/unix_socket.rs"

examples/unix_socket.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#[cfg(unix)]
2+
#[tokio::main]
3+
async fn main() -> wreq::Result<()> {
4+
// Create a Unix socket proxy
5+
let proxy = wreq::Proxy::unix("/var/run/docker.sock")?;
6+
7+
// Build a client
8+
let client = wreq::Client::builder()
9+
// Specify the Unix socket path
10+
.proxy(proxy.clone())
11+
.timeout(std::time::Duration::from_secs(10))
12+
.build()?;
13+
14+
// Use the API you're already familiar with
15+
let resp = client
16+
.get("http://localhost/v1.41/containers/json")
17+
.send()
18+
.await?;
19+
println!("{}", resp.text().await?);
20+
21+
// Or specify the Unix socket directly in the request
22+
let resp = client
23+
.get("http://localhost/v1.41/containers/json")
24+
.proxy(proxy)
25+
.send()
26+
.await?;
27+
println!("{}", resp.text().await?);
28+
29+
Ok(())
30+
}
31+
32+
#[cfg(not(unix))]
33+
fn main() {}

src/client/http/connect/conn.rs

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ use std::{
55
};
66

77
use pin_project_lite::pin_project;
8+
#[cfg(unix)]
9+
use tokio::net::UnixStream;
810
use tokio::{
911
io::{AsyncRead, AsyncWrite},
1012
net::TcpStream,
@@ -27,9 +29,9 @@ pin_project! {
2729
/// * absolute-form (`GET http://foo.bar/and/a/path HTTP/1.1`), otherwise.
2830
pub struct Conn {
2931
#[pin]
30-
inner: Box<dyn AsyncConnWithInfo>,
31-
is_proxy: bool,
32-
tls_info: bool,
32+
pub inner: Box<dyn AsyncConnWithInfo>,
33+
pub tls_info: bool,
34+
pub is_proxy: bool,
3335
}
3436
}
3537

@@ -47,18 +49,6 @@ pin_project! {
4749

4850
// ==== impl Conn ====
4951

50-
impl Conn {
51-
/// Creates a new `Conn` instance with the given inner connection and TLS info flag.
52-
#[inline(always)]
53-
pub(super) fn new(inner: Box<dyn AsyncConnWithInfo>, is_proxy: bool, tls_info: bool) -> Self {
54-
Self {
55-
inner,
56-
is_proxy,
57-
tls_info,
58-
}
59-
}
60-
}
61-
6252
impl Connection for Conn {
6353
fn connected(&self) -> Connected {
6454
let connected = self.inner.connected().proxy(self.is_proxy);
@@ -135,6 +125,8 @@ where
135125
}
136126
}
137127

128+
// ===== impl TcpStream =====
129+
138130
impl Connection for TlsConn<TcpStream> {
139131
fn connected(&self) -> Connected {
140132
let connected = self.inner.inner().get_ref().connected();
@@ -157,6 +149,32 @@ impl Connection for TlsConn<TokioIo<MaybeHttpsStream<TcpStream>>> {
157149
}
158150
}
159151

152+
// ===== impl UnixStream =====
153+
154+
#[cfg(unix)]
155+
impl Connection for TlsConn<UnixStream> {
156+
fn connected(&self) -> Connected {
157+
let connected = self.inner.inner().get_ref().connected();
158+
if self.inner.inner().ssl().selected_alpn_protocol() == Some(b"h2") {
159+
connected.negotiated_h2()
160+
} else {
161+
connected
162+
}
163+
}
164+
}
165+
166+
#[cfg(unix)]
167+
impl Connection for TlsConn<TokioIo<MaybeHttpsStream<UnixStream>>> {
168+
fn connected(&self) -> Connected {
169+
let connected = self.inner.inner().get_ref().connected();
170+
if self.inner.inner().ssl().selected_alpn_protocol() == Some(b"h2") {
171+
connected.negotiated_h2()
172+
} else {
173+
connected
174+
}
175+
}
176+
}
177+
160178
impl<T: AsyncRead + AsyncWrite + Unpin> Read for TlsConn<T> {
161179
fn poll_read(
162180
self: Pin<&mut Self>,

0 commit comments

Comments
 (0)