diff options
author | Alex <alex@adnab.me> | 2023-10-03 16:23:02 +0000 |
---|---|---|
committer | Alex <alex@adnab.me> | 2023-10-03 16:23:02 +0000 |
commit | 1243db87f2090a3302c7c8beb386e68ddf9b66b5 (patch) | |
tree | 7280b64fd8ef63be32f27f44f26f0ee7c8ca44be /src/api/generic_server.rs | |
parent | 16aa418e473a5e9ef229060d20f6eb280df272a2 (diff) | |
parent | 6f8a87814be502ecaee49cd37616ec7fe4c5b588 (diff) | |
download | garage-1243db87f2090a3302c7c8beb386e68ddf9b66b5.tar.gz garage-1243db87f2090a3302c7c8beb386e68ddf9b66b5.zip |
Merge pull request 'Add support for binding to unix domain sockets' (#640) from networkException/garage:unix-sockets into main
Reviewed-on: https://git.deuxfleurs.fr/Deuxfleurs/garage/pulls/640
Diffstat (limited to 'src/api/generic_server.rs')
-rw-r--r-- | src/api/generic_server.rs | 60 |
1 files changed, 51 insertions, 9 deletions
diff --git a/src/api/generic_server.rs b/src/api/generic_server.rs index 757b85ec..fa346f48 100644 --- a/src/api/generic_server.rs +++ b/src/api/generic_server.rs @@ -1,4 +1,5 @@ -use std::net::SocketAddr; +use std::fs::{self, Permissions}; +use std::os::unix::fs::PermissionsExt; use std::sync::Arc; use async_trait::async_trait; @@ -11,6 +12,10 @@ use hyper::service::{make_service_fn, service_fn}; use hyper::{Body, Request, Response, Server}; use hyper::{HeaderMap, StatusCode}; +use hyperlocal::UnixServerExt; + +use tokio::net::UnixStream; + use opentelemetry::{ global, metrics::{Counter, ValueRecorder}, @@ -21,6 +26,7 @@ use opentelemetry::{ use garage_util::error::Error as GarageError; use garage_util::forwarded_headers; use garage_util::metrics::{gen_trace_id, RecordDuration}; +use garage_util::socket_address::UnixOrTCPSocketAddress; pub(crate) trait ApiEndpoint: Send + Sync + 'static { fn name(&self) -> &'static str; @@ -91,10 +97,11 @@ impl<A: ApiHandler> ApiServer<A> { pub async fn run_server( self: Arc<Self>, - bind_addr: SocketAddr, + bind_addr: UnixOrTCPSocketAddress, + unix_bind_addr_mode: Option<u32>, shutdown_signal: impl Future<Output = ()>, ) -> Result<(), GarageError> { - let service = make_service_fn(|conn: &AddrStream| { + let tcp_service = make_service_fn(|conn: &AddrStream| { let this = self.clone(); let client_addr = conn.remote_addr(); @@ -102,28 +109,63 @@ impl<A: ApiHandler> ApiServer<A> { Ok::<_, GarageError>(service_fn(move |req: Request<Body>| { let this = this.clone(); - this.handler(req, client_addr) + this.handler(req, client_addr.to_string()) })) } }); - let server = Server::bind(&bind_addr).serve(service); + let unix_service = make_service_fn(|_: &UnixStream| { + let this = self.clone(); + + let path = bind_addr.to_string(); + async move { + Ok::<_, GarageError>(service_fn(move |req: Request<Body>| { + let this = this.clone(); + + this.handler(req, path.clone()) + })) + } + }); - let graceful = server.with_graceful_shutdown(shutdown_signal); info!( - "{} API server listening on http://{}", + "{} API server listening on {}", A::API_NAME_DISPLAY, bind_addr ); - graceful.await?; + match bind_addr { + UnixOrTCPSocketAddress::TCPSocket(addr) => { + Server::bind(&addr) + .serve(tcp_service) + .with_graceful_shutdown(shutdown_signal) + .await? + } + UnixOrTCPSocketAddress::UnixSocket(ref path) => { + if path.exists() { + fs::remove_file(path)? + } + + let bound = Server::bind_unix(path)?; + + fs::set_permissions( + path, + Permissions::from_mode(unix_bind_addr_mode.unwrap_or(0o222)), + )?; + + bound + .serve(unix_service) + .with_graceful_shutdown(shutdown_signal) + .await?; + } + }; + Ok(()) } async fn handler( self: Arc<Self>, req: Request<Body>, - addr: SocketAddr, + addr: String, ) -> Result<Response<Body>, GarageError> { let uri = req.uri().clone(); |