api & web unix sockets working
This commit is contained in:
parent
54e02b4c3b
commit
972426cee1
7 changed files with 164 additions and 59 deletions
15
Cargo.lock
generated
15
Cargo.lock
generated
|
@ -711,6 +711,7 @@ dependencies = [
|
||||||
"http-range",
|
"http-range",
|
||||||
"httpdate 0.3.2",
|
"httpdate 0.3.2",
|
||||||
"hyper",
|
"hyper",
|
||||||
|
"hyperlocal",
|
||||||
"idna",
|
"idna",
|
||||||
"log",
|
"log",
|
||||||
"md-5",
|
"md-5",
|
||||||
|
@ -934,6 +935,7 @@ dependencies = [
|
||||||
"garage_util 0.6.0",
|
"garage_util 0.6.0",
|
||||||
"http",
|
"http",
|
||||||
"hyper",
|
"hyper",
|
||||||
|
"hyperlocal",
|
||||||
"log",
|
"log",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
]
|
]
|
||||||
|
@ -1156,6 +1158,19 @@ dependencies = [
|
||||||
"webpki",
|
"webpki",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hyperlocal"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0fafdf7b2b2de7c9784f76e02c0935e65a8117ec3b768644379983ab333ac98c"
|
||||||
|
dependencies = [
|
||||||
|
"futures-util",
|
||||||
|
"hex",
|
||||||
|
"hyper",
|
||||||
|
"pin-project",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "idna"
|
name = "idna"
|
||||||
version = "0.2.3"
|
version = "0.2.3"
|
||||||
|
|
24
Cargo.nix
24
Cargo.nix
|
@ -1026,6 +1026,7 @@ in
|
||||||
http_range = rustPackages."registry+https://github.com/rust-lang/crates.io-index".http-range."0.1.4" { inherit profileName; };
|
http_range = rustPackages."registry+https://github.com/rust-lang/crates.io-index".http-range."0.1.4" { inherit profileName; };
|
||||||
httpdate = rustPackages."registry+https://github.com/rust-lang/crates.io-index".httpdate."0.3.2" { inherit profileName; };
|
httpdate = rustPackages."registry+https://github.com/rust-lang/crates.io-index".httpdate."0.3.2" { inherit profileName; };
|
||||||
hyper = rustPackages."registry+https://github.com/rust-lang/crates.io-index".hyper."0.14.13" { inherit profileName; };
|
hyper = rustPackages."registry+https://github.com/rust-lang/crates.io-index".hyper."0.14.13" { inherit profileName; };
|
||||||
|
hyperlocal = rustPackages."registry+https://github.com/rust-lang/crates.io-index".hyperlocal."0.8.0" { inherit profileName; };
|
||||||
idna = rustPackages."registry+https://github.com/rust-lang/crates.io-index".idna."0.2.3" { inherit profileName; };
|
idna = rustPackages."registry+https://github.com/rust-lang/crates.io-index".idna."0.2.3" { inherit profileName; };
|
||||||
log = rustPackages."registry+https://github.com/rust-lang/crates.io-index".log."0.4.14" { inherit profileName; };
|
log = rustPackages."registry+https://github.com/rust-lang/crates.io-index".log."0.4.14" { inherit profileName; };
|
||||||
md5 = rustPackages."registry+https://github.com/rust-lang/crates.io-index".md-5."0.9.1" { inherit profileName; };
|
md5 = rustPackages."registry+https://github.com/rust-lang/crates.io-index".md-5."0.9.1" { inherit profileName; };
|
||||||
|
@ -1551,6 +1552,25 @@ in
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index".hyperlocal."0.8.0" = overridableMkRustCrate (profileName: rec {
|
||||||
|
name = "hyperlocal";
|
||||||
|
version = "0.8.0";
|
||||||
|
registry = "registry+https://github.com/rust-lang/crates.io-index";
|
||||||
|
src = fetchCratesIo { inherit name version; sha256 = "0fafdf7b2b2de7c9784f76e02c0935e65a8117ec3b768644379983ab333ac98c"; };
|
||||||
|
features = builtins.concatLists [
|
||||||
|
[ "client" ]
|
||||||
|
[ "default" ]
|
||||||
|
[ "server" ]
|
||||||
|
];
|
||||||
|
dependencies = {
|
||||||
|
futures_util = rustPackages."registry+https://github.com/rust-lang/crates.io-index".futures-util."0.3.17" { inherit profileName; };
|
||||||
|
hex = rustPackages."registry+https://github.com/rust-lang/crates.io-index".hex."0.4.3" { inherit profileName; };
|
||||||
|
hyper = rustPackages."registry+https://github.com/rust-lang/crates.io-index".hyper."0.14.13" { inherit profileName; };
|
||||||
|
pin_project = rustPackages."registry+https://github.com/rust-lang/crates.io-index".pin-project."1.0.8" { inherit profileName; };
|
||||||
|
tokio = rustPackages."registry+https://github.com/rust-lang/crates.io-index".tokio."1.12.0" { inherit profileName; };
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
"registry+https://github.com/rust-lang/crates.io-index".idna."0.2.3" = overridableMkRustCrate (profileName: rec {
|
"registry+https://github.com/rust-lang/crates.io-index".idna."0.2.3" = overridableMkRustCrate (profileName: rec {
|
||||||
name = "idna";
|
name = "idna";
|
||||||
version = "0.2.3";
|
version = "0.2.3";
|
||||||
|
@ -2334,7 +2354,7 @@ in
|
||||||
];
|
];
|
||||||
dependencies = {
|
dependencies = {
|
||||||
${ if hostPlatform.parsed.kernel.name == "android" || hostPlatform.parsed.kernel.name == "linux" then "libc" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".libc."0.2.115" { inherit profileName; };
|
${ if hostPlatform.parsed.kernel.name == "android" || hostPlatform.parsed.kernel.name == "linux" then "libc" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".libc."0.2.115" { inherit profileName; };
|
||||||
${ if hostPlatform.parsed.kernel.name == "dragonfly" || hostPlatform.parsed.kernel.name == "freebsd" || hostPlatform.parsed.kernel.name == "illumos" || hostPlatform.parsed.kernel.name == "netbsd" || hostPlatform.parsed.kernel.name == "openbsd" || hostPlatform.parsed.kernel.name == "solaris" || hostPlatform.parsed.kernel.name == "android" || hostPlatform.parsed.kernel.name == "linux" then "once_cell" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".once_cell."1.8.0" { inherit profileName; };
|
${ if hostPlatform.parsed.kernel.name == "android" || hostPlatform.parsed.kernel.name == "linux" || hostPlatform.parsed.kernel.name == "dragonfly" || hostPlatform.parsed.kernel.name == "freebsd" || hostPlatform.parsed.kernel.name == "illumos" || hostPlatform.parsed.kernel.name == "netbsd" || hostPlatform.parsed.kernel.name == "openbsd" || hostPlatform.parsed.kernel.name == "solaris" then "once_cell" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".once_cell."1.8.0" { inherit profileName; };
|
||||||
${ if hostPlatform.parsed.cpu.name == "i686" || hostPlatform.parsed.cpu.name == "x86_64" || (hostPlatform.parsed.cpu.name == "aarch64" || hostPlatform.parsed.cpu.name == "armv6l" || hostPlatform.parsed.cpu.name == "armv7l") && (hostPlatform.parsed.kernel.name == "android" || hostPlatform.parsed.kernel.name == "fuchsia" || hostPlatform.parsed.kernel.name == "linux") then "spin" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".spin."0.5.2" { inherit profileName; };
|
${ if hostPlatform.parsed.cpu.name == "i686" || hostPlatform.parsed.cpu.name == "x86_64" || (hostPlatform.parsed.cpu.name == "aarch64" || hostPlatform.parsed.cpu.name == "armv6l" || hostPlatform.parsed.cpu.name == "armv7l") && (hostPlatform.parsed.kernel.name == "android" || hostPlatform.parsed.kernel.name == "fuchsia" || hostPlatform.parsed.kernel.name == "linux") then "spin" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".spin."0.5.2" { inherit profileName; };
|
||||||
untrusted = rustPackages."registry+https://github.com/rust-lang/crates.io-index".untrusted."0.7.1" { inherit profileName; };
|
untrusted = rustPackages."registry+https://github.com/rust-lang/crates.io-index".untrusted."0.7.1" { inherit profileName; };
|
||||||
${ if hostPlatform.parsed.cpu.name == "wasm32" && hostPlatform.parsed.vendor.name == "unknown" && hostPlatform.parsed.kernel.name == "unknown" && hostPlatform.parsed.abi.name == "" then "web_sys" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".web-sys."0.3.56" { inherit profileName; };
|
${ if hostPlatform.parsed.cpu.name == "wasm32" && hostPlatform.parsed.vendor.name == "unknown" && hostPlatform.parsed.kernel.name == "unknown" && hostPlatform.parsed.abi.name == "" then "web_sys" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".web-sys."0.3.56" { inherit profileName; };
|
||||||
|
@ -2704,7 +2724,7 @@ in
|
||||||
];
|
];
|
||||||
dependencies = {
|
dependencies = {
|
||||||
bitflags = rustPackages."registry+https://github.com/rust-lang/crates.io-index".bitflags."1.3.2" { inherit profileName; };
|
bitflags = rustPackages."registry+https://github.com/rust-lang/crates.io-index".bitflags."1.3.2" { inherit profileName; };
|
||||||
${ if hostPlatform.parsed.kernel.name == "linux" || hostPlatform.parsed.kernel.name == "android" then "libc" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".libc."0.2.115" { inherit profileName; };
|
${ if hostPlatform.parsed.kernel.name == "android" || hostPlatform.parsed.kernel.name == "linux" then "libc" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".libc."0.2.115" { inherit profileName; };
|
||||||
${ if !(hostPlatform.parsed.kernel.name == "linux" || hostPlatform.parsed.kernel.name == "android") then "parking_lot" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".parking_lot."0.11.2" { inherit profileName; };
|
${ if !(hostPlatform.parsed.kernel.name == "linux" || hostPlatform.parsed.kernel.name == "android") then "parking_lot" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".parking_lot."0.11.2" { inherit profileName; };
|
||||||
${ if !(hostPlatform.parsed.kernel.name == "linux" || hostPlatform.parsed.kernel.name == "android") then "parking_lot_core" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".parking_lot_core."0.8.5" { inherit profileName; };
|
${ if !(hostPlatform.parsed.kernel.name == "linux" || hostPlatform.parsed.kernel.name == "android") then "parking_lot_core" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".parking_lot_core."0.8.5" { inherit profileName; };
|
||||||
static_init_macro = buildRustPackages."registry+https://github.com/rust-lang/crates.io-index".static_init_macro."1.0.2" { profileName = "__noProfile"; };
|
static_init_macro = buildRustPackages."registry+https://github.com/rust-lang/crates.io-index".static_init_macro."1.0.2" { profileName = "__noProfile"; };
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
[package]
|
[package]
|
||||||
name = "garage_api"
|
|
||||||
version = "0.6.0"
|
|
||||||
authors = ["Alex Auvolat <alex@adnab.me>"]
|
authors = ["Alex Auvolat <alex@adnab.me>"]
|
||||||
|
description = "S3 API server crate for the Garage object store"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
license = "AGPL-3.0"
|
license = "AGPL-3.0"
|
||||||
description = "S3 API server crate for the Garage object store"
|
name = "garage_api"
|
||||||
repository = "https://git.deuxfleurs.fr/Deuxfleurs/garage"
|
|
||||||
readme = "../../README.md"
|
readme = "../../README.md"
|
||||||
|
repository = "https://git.deuxfleurs.fr/Deuxfleurs/garage"
|
||||||
|
version = "0.6.0"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
path = "lib.rs"
|
path = "lib.rs"
|
||||||
|
@ -38,14 +38,15 @@ tokio = { version = "1.0", default-features = false, features = ["rt", "rt-multi
|
||||||
|
|
||||||
form_urlencoded = "1.0.0"
|
form_urlencoded = "1.0.0"
|
||||||
http = "0.2"
|
http = "0.2"
|
||||||
httpdate = "0.3"
|
|
||||||
http-range = "0.1"
|
http-range = "0.1"
|
||||||
|
httpdate = "0.3"
|
||||||
hyper = {version = "0.14", features = ["server", "http1", "runtime", "tcp", "stream"]}
|
hyper = {version = "0.14", features = ["server", "http1", "runtime", "tcp", "stream"]}
|
||||||
|
hyperlocal = "0.8"
|
||||||
multer = "2.0"
|
multer = "2.0"
|
||||||
percent-encoding = "2.1.0"
|
percent-encoding = "2.1.0"
|
||||||
|
quick-xml = {version = "0.21", features = ["serialize"]}
|
||||||
roxmltree = "0.14"
|
roxmltree = "0.14"
|
||||||
serde = {version = "1.0", features = ["derive"]}
|
serde = {version = "1.0", features = ["derive"]}
|
||||||
serde_bytes = "0.11"
|
serde_bytes = "0.11"
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
quick-xml = { version = "0.21", features = [ "serialize" ] }
|
|
||||||
url = "2.1"
|
url = "2.1"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use std::net::SocketAddr;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use std::{fs, path::Path};
|
||||||
|
|
||||||
use futures::future::Future;
|
use futures::future::Future;
|
||||||
use hyper::header;
|
use hyper::header;
|
||||||
|
@ -7,6 +7,8 @@ use hyper::server::conn::AddrStream;
|
||||||
use hyper::service::{make_service_fn, service_fn};
|
use hyper::service::{make_service_fn, service_fn};
|
||||||
use hyper::{Body, Method, Request, Response, Server};
|
use hyper::{Body, Method, Request, Response, Server};
|
||||||
|
|
||||||
|
use hyperlocal::UnixServerExt;
|
||||||
|
|
||||||
use garage_util::data::*;
|
use garage_util::data::*;
|
||||||
use garage_util::error::Error as GarageError;
|
use garage_util::error::Error as GarageError;
|
||||||
|
|
||||||
|
@ -35,32 +37,57 @@ pub async fn run_api_server(
|
||||||
garage: Arc<Garage>,
|
garage: Arc<Garage>,
|
||||||
shutdown_signal: impl Future<Output = ()>,
|
shutdown_signal: impl Future<Output = ()>,
|
||||||
) -> Result<(), GarageError> {
|
) -> Result<(), GarageError> {
|
||||||
|
let socket_path = &garage.config.s3_api.api_unix_socket;
|
||||||
|
if socket_path.is_empty() {
|
||||||
let addr = &garage.config.s3_api.api_bind_addr;
|
let addr = &garage.config.s3_api.api_bind_addr;
|
||||||
|
|
||||||
let service = make_service_fn(|conn: &AddrStream| {
|
let service = make_service_fn(|conn: &AddrStream| {
|
||||||
let garage = garage.clone();
|
let garage = garage.clone();
|
||||||
let client_addr = conn.remote_addr();
|
let client_addr = conn.remote_addr().to_string();
|
||||||
async move {
|
async move {
|
||||||
Ok::<_, GarageError>(service_fn(move |req: Request<Body>| {
|
Ok::<_, GarageError>(service_fn(move |req: Request<Body>| {
|
||||||
let garage = garage.clone();
|
let garage = garage.clone();
|
||||||
handler(garage, req, client_addr)
|
handler(garage, req, client_addr.clone())
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let server = Server::bind(addr).serve(service);
|
let server = Server::bind(addr).serve(service);
|
||||||
|
|
||||||
let graceful = server.with_graceful_shutdown(shutdown_signal);
|
let graceful = server.with_graceful_shutdown(shutdown_signal);
|
||||||
info!("API server listening on http://{}", addr);
|
|
||||||
|
|
||||||
|
info!("API server listening on http://{}", addr);
|
||||||
graceful.await?;
|
graceful.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
} else {
|
||||||
|
let path = Path::new(socket_path);
|
||||||
|
if path.exists() {
|
||||||
|
fs::remove_file(path)?;
|
||||||
|
}
|
||||||
|
let service = make_service_fn(|_conn| {
|
||||||
|
let garage = garage.clone();
|
||||||
|
let client_addr = String::from("unix");
|
||||||
|
async move {
|
||||||
|
Ok::<_, GarageError>(service_fn(move |req: Request<Body>| {
|
||||||
|
let garage = garage.clone();
|
||||||
|
handler(garage, req, client_addr.clone())
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let listener = Server::bind_unix(path)?;
|
||||||
|
let server = listener.serve(service);
|
||||||
|
let graceful = server.with_graceful_shutdown(shutdown_signal);
|
||||||
|
|
||||||
|
info!("API server listening on {}", socket_path);
|
||||||
|
graceful.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handler(
|
async fn handler(
|
||||||
garage: Arc<Garage>,
|
garage: Arc<Garage>,
|
||||||
req: Request<Body>,
|
req: Request<Body>,
|
||||||
addr: SocketAddr,
|
addr: String,
|
||||||
) -> Result<Response<Body>, GarageError> {
|
) -> Result<Response<Body>, GarageError> {
|
||||||
let uri = req.uri().clone();
|
let uri = req.uri().clone();
|
||||||
info!("{} {} {}", addr, req.method(), uri);
|
info!("{} {} {}", addr, req.method(), uri);
|
||||||
|
|
|
@ -37,6 +37,10 @@ pub struct Config {
|
||||||
)]
|
)]
|
||||||
pub compression_level: Option<i32>,
|
pub compression_level: Option<i32>,
|
||||||
|
|
||||||
|
/// Path to unix socket
|
||||||
|
#[serde(default = "default_unix_socket")]
|
||||||
|
pub rpc_unix_socket: String,
|
||||||
|
|
||||||
/// RPC secret key: 32 bytes hex encoded
|
/// RPC secret key: 32 bytes hex encoded
|
||||||
pub rpc_secret: String,
|
pub rpc_secret: String,
|
||||||
|
|
||||||
|
@ -71,6 +75,9 @@ pub struct Config {
|
||||||
/// Configuration for S3 api
|
/// Configuration for S3 api
|
||||||
#[derive(Deserialize, Debug, Clone)]
|
#[derive(Deserialize, Debug, Clone)]
|
||||||
pub struct ApiConfig {
|
pub struct ApiConfig {
|
||||||
|
/// Path to unix socket
|
||||||
|
#[serde(default = "default_unix_socket")]
|
||||||
|
pub api_unix_socket: String,
|
||||||
/// Address and port to bind for api serving
|
/// Address and port to bind for api serving
|
||||||
pub api_bind_addr: SocketAddr,
|
pub api_bind_addr: SocketAddr,
|
||||||
/// S3 region to use
|
/// S3 region to use
|
||||||
|
@ -83,6 +90,9 @@ pub struct ApiConfig {
|
||||||
/// Configuration for serving files as normal web server
|
/// Configuration for serving files as normal web server
|
||||||
#[derive(Deserialize, Debug, Clone)]
|
#[derive(Deserialize, Debug, Clone)]
|
||||||
pub struct WebConfig {
|
pub struct WebConfig {
|
||||||
|
/// Path to unix socket
|
||||||
|
#[serde(default = "default_unix_socket")]
|
||||||
|
pub web_unix_socket: String,
|
||||||
/// Address and port to bind for web serving
|
/// Address and port to bind for web serving
|
||||||
pub bind_addr: SocketAddr,
|
pub bind_addr: SocketAddr,
|
||||||
/// Suffix to remove from domain name to find bucket
|
/// Suffix to remove from domain name to find bucket
|
||||||
|
@ -98,6 +108,9 @@ fn default_sled_flush_every_ms() -> u64 {
|
||||||
fn default_block_size() -> usize {
|
fn default_block_size() -> usize {
|
||||||
1048576
|
1048576
|
||||||
}
|
}
|
||||||
|
fn default_unix_socket() -> String {
|
||||||
|
String::new()
|
||||||
|
}
|
||||||
|
|
||||||
/// Read and parse configuration
|
/// Read and parse configuration
|
||||||
pub fn read_config(config_file: PathBuf) -> Result<Config, Error> {
|
pub fn read_config(config_file: PathBuf) -> Result<Config, Error> {
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
[package]
|
[package]
|
||||||
name = "garage_web"
|
|
||||||
version = "0.6.0"
|
|
||||||
authors = ["Alex Auvolat <alex@adnab.me>", "Quentin Dufour <quentin@dufour.io>"]
|
authors = ["Alex Auvolat <alex@adnab.me>", "Quentin Dufour <quentin@dufour.io>"]
|
||||||
|
description = "S3-like website endpoint crate for the Garage object store"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
license = "AGPL-3.0"
|
license = "AGPL-3.0"
|
||||||
description = "S3-like website endpoint crate for the Garage object store"
|
name = "garage_web"
|
||||||
repository = "https://git.deuxfleurs.fr/Deuxfleurs/garage"
|
|
||||||
readme = "../../README.md"
|
readme = "../../README.md"
|
||||||
|
repository = "https://git.deuxfleurs.fr/Deuxfleurs/garage"
|
||||||
|
version = "0.6.0"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
path = "lib.rs"
|
path = "lib.rs"
|
||||||
|
@ -16,8 +16,8 @@ path = "lib.rs"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
garage_api = {version = "0.6.0", path = "../api"}
|
garage_api = {version = "0.6.0", path = "../api"}
|
||||||
garage_model = {version = "0.6.0", path = "../model"}
|
garage_model = {version = "0.6.0", path = "../model"}
|
||||||
garage_util = { version = "0.6.0", path = "../util" }
|
|
||||||
garage_table = {version = "0.6.0", path = "../table"}
|
garage_table = {version = "0.6.0", path = "../table"}
|
||||||
|
garage_util = {version = "0.6.0", path = "../util"}
|
||||||
|
|
||||||
err-derive = "0.3"
|
err-derive = "0.3"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
@ -27,3 +27,4 @@ futures = "0.3"
|
||||||
|
|
||||||
http = "0.2"
|
http = "0.2"
|
||||||
hyper = {version = "0.14", features = ["server", "http1", "runtime", "tcp", "stream"]}
|
hyper = {version = "0.14", features = ["server", "http1", "runtime", "tcp", "stream"]}
|
||||||
|
hyperlocal = "0.8"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::{borrow::Cow, convert::Infallible, net::SocketAddr, sync::Arc};
|
use std::{borrow::Cow, convert::Infallible, fs, path::Path, sync::Arc};
|
||||||
|
|
||||||
use futures::future::Future;
|
use futures::future::Future;
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@ use hyper::{
|
||||||
Body, Method, Request, Response, Server,
|
Body, Method, Request, Response, Server,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use hyperlocal::UnixServerExt;
|
||||||
|
|
||||||
use crate::error::*;
|
use crate::error::*;
|
||||||
|
|
||||||
use garage_api::error::{Error as ApiError, OkOrBadRequest, OkOrInternalError};
|
use garage_api::error::{Error as ApiError, OkOrBadRequest, OkOrInternalError};
|
||||||
|
@ -26,31 +28,57 @@ pub async fn run_web_server(
|
||||||
garage: Arc<Garage>,
|
garage: Arc<Garage>,
|
||||||
shutdown_signal: impl Future<Output = ()>,
|
shutdown_signal: impl Future<Output = ()>,
|
||||||
) -> Result<(), GarageError> {
|
) -> Result<(), GarageError> {
|
||||||
|
let socket_path = &garage.config.s3_web.web_unix_socket;
|
||||||
|
if socket_path.is_empty() {
|
||||||
let addr = &garage.config.s3_web.bind_addr;
|
let addr = &garage.config.s3_web.bind_addr;
|
||||||
|
|
||||||
let service = make_service_fn(|conn: &AddrStream| {
|
let service = make_service_fn(|conn: &AddrStream| {
|
||||||
let garage = garage.clone();
|
let garage = garage.clone();
|
||||||
let client_addr = conn.remote_addr();
|
let client_addr = conn.remote_addr().to_string();
|
||||||
async move {
|
async move {
|
||||||
Ok::<_, Error>(service_fn(move |req: Request<Body>| {
|
Ok::<_, GarageError>(service_fn(move |req: Request<Body>| {
|
||||||
let garage = garage.clone();
|
let garage = garage.clone();
|
||||||
handle_request(garage, req, client_addr)
|
handler(garage, req, client_addr.clone())
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let server = Server::bind(addr).serve(service);
|
let server = Server::bind(addr).serve(service);
|
||||||
let graceful = server.with_graceful_shutdown(shutdown_signal);
|
let graceful = server.with_graceful_shutdown(shutdown_signal);
|
||||||
info!("Web server listening on http://{}", addr);
|
|
||||||
|
|
||||||
|
info!("Web server listening on http://{}", addr);
|
||||||
|
graceful.await?;
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
let path = Path::new(socket_path);
|
||||||
|
if path.exists() {
|
||||||
|
fs::remove_file(path)?;
|
||||||
|
}
|
||||||
|
let service = make_service_fn(|_conn| {
|
||||||
|
let garage = garage.clone();
|
||||||
|
let client_addr = String::from("unix");
|
||||||
|
async move {
|
||||||
|
Ok::<_, GarageError>(service_fn(move |req: Request<Body>| {
|
||||||
|
let garage = garage.clone();
|
||||||
|
handler(garage, req, client_addr.clone())
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let listener = Server::bind_unix(path)?;
|
||||||
|
let server = listener.serve(service);
|
||||||
|
let graceful = server.with_graceful_shutdown(shutdown_signal);
|
||||||
|
|
||||||
|
info!("Web server listening on {}", socket_path);
|
||||||
graceful.await?;
|
graceful.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async fn handle_request(
|
async fn handler(
|
||||||
garage: Arc<Garage>,
|
garage: Arc<Garage>,
|
||||||
req: Request<Body>,
|
req: Request<Body>,
|
||||||
addr: SocketAddr,
|
addr: String,
|
||||||
) -> Result<Response<Body>, Infallible> {
|
) -> Result<Response<Body>, Infallible> {
|
||||||
info!("{} {} {}", addr, req.method(), req.uri());
|
info!("{} {} {}", addr, req.method(), req.uri());
|
||||||
match serve_file(garage, &req).await {
|
match serve_file(garage, &req).await {
|
||||||
|
|
Loading…
Reference in a new issue