1use actix_rt::net::UnixStream;
16use actix_service::Service;
17use actix_tls::connect::{ConnectError, ConnectInfo, Connection};
18use awc::http::Uri;
19use std::future::Future;
20use std::path::{Path, PathBuf};
21use std::pin::Pin;
22use std::task::{Context, Poll};
23
24type Fut<R, E> = Pin<Box<dyn Future<Output = Result<R, E>>>>;
25
26#[derive(Clone)]
27pub struct UdsConnector(PathBuf);
28
29impl UdsConnector {
30 pub fn new(path: impl AsRef<Path>) -> Self {
31 UdsConnector(path.as_ref().to_path_buf())
32 }
33}
34
35impl Service<ConnectInfo<Uri>> for UdsConnector {
36 type Response = Connection<Uri, UnixStream>;
37 type Error = ConnectError;
38 type Future = Fut<Self::Response, Self::Error>;
39
40 fn poll_ready(&self, _ctx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
41 Poll::Ready(Ok(()))
42 }
43
44 fn call(&self, req: ConnectInfo<Uri>) -> Self::Future {
45 let uri = req.request().clone();
46 let path = self.0.clone();
47 let fut = async {
48 let stream = UnixStream::connect(path).await.map_err(ConnectError::Io)?;
49 Ok(Connection::new(uri, stream))
50 };
51 Box::pin(fut)
52 }
53}
54
55#[cfg(test)]
56mod tests {
57 #[actix_rt::test]
58 async fn it_works() {
59 use super::UdsConnector;
60 use actix_web::{get, App, HttpRequest, HttpServer};
61 use awc::{ClientBuilder, Connector};
62 use std::time::Duration;
63 use tempfile::tempdir;
64
65 let socket_dir = tempdir().unwrap();
66 let socket_path = socket_dir.path().join("awc-uds.sock");
67 let socket_path2 = socket_path.clone();
68
69 #[get("/")]
70 async fn hello(_req: HttpRequest) -> String {
71 "hello".to_string()
72 }
73 let _handle = actix_rt::spawn(async {
74 let _server = HttpServer::new(|| App::new().service(hello))
75 .bind_uds(socket_path)
76 .unwrap()
77 .run()
78 .await;
79 });
80
81 actix_rt::time::sleep(Duration::from_secs(1)).await;
82 let connector = Connector::new().connector(UdsConnector::new(socket_path2));
83 let client = ClientBuilder::new().connector(connector).finish();
84 let resp = client
85 .get("http://localhost/")
86 .send()
87 .await
88 .unwrap()
89 .body()
90 .await
91 .unwrap();
92 assert_eq!(resp, b"hello".as_ref());
93 println!("{:?}", resp);
94 }
95}