mirror of
https://codeberg.org/icewind/haze.git
synced 2026-06-03 17:14:08 +02:00
switch proxy to allow webscokets
This commit is contained in:
parent
2a7f4de2b7
commit
6aad67473d
4 changed files with 111 additions and 208 deletions
134
Cargo.lock
generated
134
Cargo.lock
generated
|
|
@ -511,6 +511,8 @@ dependencies = [
|
||||||
"enum_dispatch",
|
"enum_dispatch",
|
||||||
"flate2",
|
"flate2",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
|
"hyper",
|
||||||
|
"hyper-reverse-proxy",
|
||||||
"maplit",
|
"maplit",
|
||||||
"miette",
|
"miette",
|
||||||
"opener",
|
"opener",
|
||||||
|
|
@ -527,7 +529,6 @@ dependencies = [
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
"warp",
|
"warp",
|
||||||
"warp-reverse-proxy",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -603,9 +604,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "httparse"
|
name = "httparse"
|
||||||
version = "1.7.1"
|
version = "1.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c"
|
checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "httpdate"
|
name = "httpdate"
|
||||||
|
|
@ -615,9 +616,9 @@ checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper"
|
name = "hyper"
|
||||||
version = "0.14.20"
|
version = "0.14.24"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac"
|
checksum = "5e011372fa0b68db8350aa7a248930ecc7839bf46d8485577d69f117a75f164c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
|
|
@ -638,16 +639,14 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper-rustls"
|
name = "hyper-reverse-proxy"
|
||||||
version = "0.23.0"
|
version = "0.5.2-dev"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/felipenoris/hyper-reverse-proxy#e73a76600ce9e51e962de5266b03be596e6c1d50"
|
||||||
checksum = "d87c48c02e0dc5e3b849a2041db3029fd066650f8f717c07bf8ed78ccb895cac"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"http",
|
|
||||||
"hyper",
|
"hyper",
|
||||||
"rustls",
|
"lazy_static",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-rustls",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -1148,7 +1147,6 @@ dependencies = [
|
||||||
"http",
|
"http",
|
||||||
"http-body",
|
"http-body",
|
||||||
"hyper",
|
"hyper",
|
||||||
"hyper-rustls",
|
|
||||||
"ipnet",
|
"ipnet",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
|
|
@ -1156,64 +1154,24 @@ dependencies = [
|
||||||
"mime",
|
"mime",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"rustls",
|
|
||||||
"rustls-pemfile",
|
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_urlencoded",
|
"serde_urlencoded",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-rustls",
|
|
||||||
"tower-service",
|
"tower-service",
|
||||||
"url",
|
"url",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"wasm-bindgen-futures",
|
"wasm-bindgen-futures",
|
||||||
"web-sys",
|
"web-sys",
|
||||||
"webpki-roots",
|
|
||||||
"winreg",
|
"winreg",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ring"
|
|
||||||
version = "0.16.20"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
|
|
||||||
dependencies = [
|
|
||||||
"cc",
|
|
||||||
"libc",
|
|
||||||
"once_cell",
|
|
||||||
"spin",
|
|
||||||
"untrusted",
|
|
||||||
"web-sys",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-demangle"
|
name = "rustc-demangle"
|
||||||
version = "0.1.21"
|
version = "0.1.21"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
|
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rustls"
|
|
||||||
version = "0.20.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5aab8ee6c7097ed6057f43c187a62418d0c05a4bd5f18b3571db50ee0f9ce033"
|
|
||||||
dependencies = [
|
|
||||||
"log",
|
|
||||||
"ring",
|
|
||||||
"sct",
|
|
||||||
"webpki",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rustls-pemfile"
|
|
||||||
version = "1.0.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0864aeff53f8c05aa08d86e5ef839d3dfcf07aeba2db32f12db0ef716e87bd55"
|
|
||||||
dependencies = [
|
|
||||||
"base64",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.10"
|
version = "1.0.10"
|
||||||
|
|
@ -1232,16 +1190,6 @@ version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
|
checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "sct"
|
|
||||||
version = "0.7.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4"
|
|
||||||
dependencies = [
|
|
||||||
"ring",
|
|
||||||
"untrusted",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.142"
|
version = "1.0.142"
|
||||||
|
|
@ -1378,20 +1326,14 @@ checksum = "f67ad224767faa3c7d8b6d91985b78e70a1324408abcb1cfcc2be4c06bc06043"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "socket2"
|
name = "socket2"
|
||||||
version = "0.4.4"
|
version = "0.4.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0"
|
checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "spin"
|
|
||||||
version = "0.5.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strsim"
|
name = "strsim"
|
||||||
version = "0.10.0"
|
version = "0.10.0"
|
||||||
|
|
@ -1626,17 +1568,6 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tokio-rustls"
|
|
||||||
version = "0.23.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59"
|
|
||||||
dependencies = [
|
|
||||||
"rustls",
|
|
||||||
"tokio",
|
|
||||||
"webpki",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-stream"
|
name = "tokio-stream"
|
||||||
version = "0.1.9"
|
version = "0.1.9"
|
||||||
|
|
@ -1854,12 +1785,6 @@ version = "0.1.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
|
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "untrusted"
|
|
||||||
version = "0.7.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "url"
|
name = "url"
|
||||||
version = "2.2.2"
|
version = "2.2.2"
|
||||||
|
|
@ -1930,20 +1855,6 @@ dependencies = [
|
||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "warp-reverse-proxy"
|
|
||||||
version = "0.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "21bb86f4c86d0fb386acf34fa5360ea0e8a082835e05296da2286c38a3316283"
|
|
||||||
dependencies = [
|
|
||||||
"hyper",
|
|
||||||
"once_cell",
|
|
||||||
"reqwest",
|
|
||||||
"thiserror",
|
|
||||||
"unicase",
|
|
||||||
"warp",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasi"
|
name = "wasi"
|
||||||
version = "0.11.0+wasi-snapshot-preview1"
|
version = "0.11.0+wasi-snapshot-preview1"
|
||||||
|
|
@ -2026,25 +1937,6 @@ dependencies = [
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "webpki"
|
|
||||||
version = "0.22.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd"
|
|
||||||
dependencies = [
|
|
||||||
"ring",
|
|
||||||
"untrusted",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "webpki-roots"
|
|
||||||
version = "0.22.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f1c760f0d366a6c24a02ed7816e23e691f5d92291f94d15e836006fd11b04daf"
|
|
||||||
dependencies = [
|
|
||||||
"webpki",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
|
|
|
||||||
|
|
@ -28,10 +28,11 @@ enum_dispatch = "0.3.8"
|
||||||
miette = { version = "5.2.0", features = ["fancy"] }
|
miette = { version = "5.2.0", features = ["fancy"] }
|
||||||
shell-words = "1.1.0"
|
shell-words = "1.1.0"
|
||||||
warp = "0.3"
|
warp = "0.3"
|
||||||
warp-reverse-proxy = { version = "0.5.0", default_features = false, features = ["rustls-tls"] }
|
|
||||||
tokio-stream = { version = "0.1.9", features = ["net"] }
|
tokio-stream = { version = "0.1.9", features = ["net"] }
|
||||||
tracing = "0.1.35"
|
tracing = "0.1.35"
|
||||||
tracing-subscriber = "0.3.14"
|
tracing-subscriber = "0.3.14"
|
||||||
|
hyper-reverse-proxy = { version = "0.5.2-dev", git = "https://github.com/felipenoris/hyper-reverse-proxy" }
|
||||||
|
hyper = "0.14.24"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
lto = true
|
lto = true
|
||||||
|
|
|
||||||
|
|
@ -37,12 +37,13 @@ haze start [database] [php-version]
|
||||||
```
|
```
|
||||||
|
|
||||||
Where `database` is one of `sqlite`, `mysql`, `mariadb` or `pgsql` with an optional version (e.g. `pgsql:12`), defaults to `sqlite`.
|
Where `database` is one of `sqlite`, `mysql`, `mariadb` or `pgsql` with an optional version (e.g. `pgsql:12`), defaults to `sqlite`.
|
||||||
And `php-version` is one of `7.3`, `7.4`, `8.0`, `7` or `8`, defaults to `8.0`
|
And `php-version` is one of `7.3`, `7.4`, `8.0`, `8.1`, `7` or `8`, defaults to `8.1`
|
||||||
|
|
||||||
Additionally, you can use the following options when starting an instance:
|
Additionally, you can use the following options when starting an instance:
|
||||||
- `s3`: setup an S3 server and configure to Nextcloud to use it as primary storage
|
- `s3`: setup an S3 server and configure to Nextcloud to use it as primary storage
|
||||||
- `<path to app.tar.gz>`: by specifying the path to an app package this package will be extracted into the apps directory of the new instance (overwriting any existing app code). This can be used to quickly test a packaged app.
|
- `<path to app.tar.gz>`: by specifying the path to an app package this package will be extracted into the apps directory of the new instance (overwriting any existing app code). This can be used to quickly test a packaged app.
|
||||||
- `ldap`: setup an LDAP server
|
- `ldap`: setup an LDAP server
|
||||||
|
- `office`: setup a Nextcloud Office server
|
||||||
- `onlyoffice` setup an onlyoffice document server
|
- `onlyoffice` setup an onlyoffice document server
|
||||||
- `push` setup [client push](https://github.com/nextcloud/notify_push)
|
- `push` setup [client push](https://github.com/nextcloud/notify_push)
|
||||||
- `smb`: setup a samba server for external storage use
|
- `smb`: setup a samba server for external storage use
|
||||||
|
|
|
||||||
179
src/proxy.rs
179
src/proxy.rs
|
|
@ -2,31 +2,29 @@ use crate::service::ServiceTrait;
|
||||||
use crate::{Cloud, HazeConfig};
|
use crate::{Cloud, HazeConfig};
|
||||||
use crate::{Result, Service};
|
use crate::{Result, Service};
|
||||||
use bollard::Docker;
|
use bollard::Docker;
|
||||||
use futures_util::future::Either;
|
use hyper::http::uri::Builder;
|
||||||
use futures_util::FutureExt;
|
use miette::{miette, IntoDiagnostic};
|
||||||
use miette::{miette, Context, IntoDiagnostic};
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::convert::Infallible;
|
||||||
use std::fs::{create_dir_all, remove_file, set_permissions};
|
use std::fs::{create_dir_all, remove_file, set_permissions};
|
||||||
use std::net::SocketAddr;
|
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||||
use std::os::unix::fs::PermissionsExt;
|
use std::os::unix::fs::PermissionsExt;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::str::FromStr;
|
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use tokio::net::UnixListener;
|
use tokio::net::{UnixListener, UnixStream};
|
||||||
use tokio::signal::ctrl_c;
|
use tokio::signal::ctrl_c;
|
||||||
use tokio::spawn;
|
use tokio::spawn;
|
||||||
use tokio::time::sleep;
|
use tokio::time::sleep;
|
||||||
use tokio_stream::wrappers::UnixListenerStream;
|
use tokio_stream::wrappers::UnixListenerStream;
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
use warp::host::Authority;
|
use warp::host::Authority;
|
||||||
use warp::http::{HeaderMap, HeaderValue, Method};
|
use warp::http::header::HOST;
|
||||||
use warp::hyper::body::Bytes;
|
use warp::http::{HeaderValue, Uri};
|
||||||
use warp::path::FullPath;
|
use warp::hyper::server::accept::from_stream;
|
||||||
use warp::Filter;
|
use warp::hyper::server::conn::AddrStream;
|
||||||
use warp_reverse_proxy::{
|
use warp::hyper::service::{make_service_fn, service_fn};
|
||||||
extract_request_data_filter, proxy_to_and_forward_response, QueryParameters,
|
use warp::hyper::{Body, Request, Response, Server, StatusCode};
|
||||||
};
|
|
||||||
|
|
||||||
struct ActiveInstances {
|
struct ActiveInstances {
|
||||||
known: Mutex<HashMap<String, SocketAddr>>,
|
known: Mutex<HashMap<String, SocketAddr>>,
|
||||||
|
|
@ -126,8 +124,6 @@ async fn serve(instances: ActiveInstances, listen: String, base_address: String)
|
||||||
let instances = Arc::new(instances);
|
let instances = Arc::new(instances);
|
||||||
let base_address = Arc::new(base_address);
|
let base_address = Arc::new(base_address);
|
||||||
let last_instances = instances.clone();
|
let last_instances = instances.clone();
|
||||||
let instances = warp::any().map(move || instances.clone());
|
|
||||||
let base_address = warp::any().map(move || base_address.clone());
|
|
||||||
|
|
||||||
spawn(async move {
|
spawn(async move {
|
||||||
loop {
|
loop {
|
||||||
|
|
@ -136,73 +132,31 @@ async fn serve(instances: ActiveInstances, listen: String, base_address: String)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let proxy = warp::any()
|
|
||||||
.and(warp::filters::host::optional())
|
|
||||||
.and(instances)
|
|
||||||
.and(base_address)
|
|
||||||
.and_then(
|
|
||||||
move |host: Option<Authority>,
|
|
||||||
instances: Arc<ActiveInstances>,
|
|
||||||
base_address: Arc<String>| async move {
|
|
||||||
let host = match host {
|
|
||||||
Some(host) => host,
|
|
||||||
None => return Err(warp::reject::not_found()),
|
|
||||||
};
|
|
||||||
let ip = if host.as_str() == base_address.as_str() {
|
|
||||||
instances
|
|
||||||
.last()
|
|
||||||
.ok_or_else(|| String::from("No running instance known"))
|
|
||||||
} else {
|
|
||||||
let requested_instance = host.as_str().split('.').next().unwrap();
|
|
||||||
instances
|
|
||||||
.get(requested_instance)
|
|
||||||
.await
|
|
||||||
.ok_or_else(|| format!("Error {} has no known ip", requested_instance))
|
|
||||||
};
|
|
||||||
match ip {
|
|
||||||
Ok(ip) => Ok((format!("http://{}", ip), host.to_string())),
|
|
||||||
Err(e) => {
|
|
||||||
eprintln!("{}", e);
|
|
||||||
Err(warp::reject::not_found())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.untuple_one()
|
|
||||||
.and(extract_request_data_filter())
|
|
||||||
.and_then(
|
|
||||||
move |proxy_address: String,
|
|
||||||
host: String,
|
|
||||||
uri: FullPath,
|
|
||||||
params: QueryParameters,
|
|
||||||
method: Method,
|
|
||||||
mut headers: HeaderMap,
|
|
||||||
body: Bytes| {
|
|
||||||
headers.insert("host", HeaderValue::from_str(&host).unwrap());
|
|
||||||
proxy_to_and_forward_response(
|
|
||||||
proxy_address,
|
|
||||||
String::new(),
|
|
||||||
uri,
|
|
||||||
params,
|
|
||||||
method,
|
|
||||||
headers,
|
|
||||||
body,
|
|
||||||
)
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
let cancel = async {
|
let cancel = async {
|
||||||
ctrl_c().await.ok();
|
ctrl_c().await.ok();
|
||||||
};
|
};
|
||||||
|
|
||||||
let warp_server = warp::serve(proxy);
|
let handler = move |remote_addr| {
|
||||||
|
let instances = instances.clone();
|
||||||
|
let base_address = base_address.clone();
|
||||||
|
async move {
|
||||||
|
Ok::<_, Infallible>(service_fn(move |req| {
|
||||||
|
handle(remote_addr, req, instances.clone(), base_address.clone())
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let server = if !listen.starts_with('/') {
|
if !listen.starts_with('/') {
|
||||||
let listen = SocketAddr::from_str(&listen)
|
let make_svc = make_service_fn(|conn: &AddrStream| handler(conn.remote_addr().ip()));
|
||||||
.into_diagnostic()
|
let addr: SocketAddr = listen.parse().into_diagnostic()?;
|
||||||
.wrap_err("Failed to parse proxy listen address")?;
|
Server::bind(&addr)
|
||||||
Either::Left(warp_server.bind_with_graceful_shutdown(listen, cancel).1)
|
.serve(make_svc)
|
||||||
|
.with_graceful_shutdown(cancel)
|
||||||
|
.await
|
||||||
|
.into_diagnostic()?;
|
||||||
} else {
|
} else {
|
||||||
|
let make_svc =
|
||||||
|
make_service_fn(move |_conn: &UnixStream| handler(Ipv4Addr::UNSPECIFIED.into()));
|
||||||
let listen: PathBuf = listen.into();
|
let listen: PathBuf = listen.into();
|
||||||
if let Some(parent) = listen.parent() {
|
if let Some(parent) = listen.parent() {
|
||||||
if !parent.exists() {
|
if !parent.exists() {
|
||||||
|
|
@ -215,15 +169,70 @@ async fn serve(instances: ActiveInstances, listen: String, base_address: String)
|
||||||
let listener = UnixListener::bind(&listen).into_diagnostic()?;
|
let listener = UnixListener::bind(&listen).into_diagnostic()?;
|
||||||
set_permissions(&listen, PermissionsExt::from_mode(0o666)).into_diagnostic()?;
|
set_permissions(&listen, PermissionsExt::from_mode(0o666)).into_diagnostic()?;
|
||||||
let stream = UnixListenerStream::new(listener);
|
let stream = UnixListenerStream::new(listener);
|
||||||
Either::Right(
|
let acceptor = from_stream(stream);
|
||||||
warp_server
|
Server::builder(acceptor)
|
||||||
.serve_incoming_with_graceful_shutdown(stream, cancel)
|
.serve(make_svc)
|
||||||
.map(move |_| {
|
.with_graceful_shutdown(cancel)
|
||||||
remove_file(&listen).ok();
|
.await
|
||||||
}),
|
.into_diagnostic()?;
|
||||||
)
|
}
|
||||||
};
|
|
||||||
|
|
||||||
server.await;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn get_remote(
|
||||||
|
host: Option<&HeaderValue>,
|
||||||
|
instances: &ActiveInstances,
|
||||||
|
base_address: &str,
|
||||||
|
) -> Result<SocketAddr, String> {
|
||||||
|
let host = match host.and_then(|host| host.to_str().ok()) {
|
||||||
|
Some(host) => host,
|
||||||
|
None => return Err("No or invalid hostname provided".into()),
|
||||||
|
};
|
||||||
|
let ip = if host == base_address {
|
||||||
|
instances
|
||||||
|
.last()
|
||||||
|
.ok_or_else(|| String::from("No running instance known"))
|
||||||
|
} else {
|
||||||
|
let requested_instance = host.split('.').next().unwrap();
|
||||||
|
instances
|
||||||
|
.get(requested_instance)
|
||||||
|
.await
|
||||||
|
.ok_or_else(|| format!("Error {} has no known ip", requested_instance))
|
||||||
|
};
|
||||||
|
match ip {
|
||||||
|
Ok(ip) => Ok(ip),
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("{}", e);
|
||||||
|
Err(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn handle(
|
||||||
|
client_ip: IpAddr,
|
||||||
|
req: Request<Body>,
|
||||||
|
instances: Arc<ActiveInstances>,
|
||||||
|
base_address: Arc<String>,
|
||||||
|
) -> Result<Response<Body>, Infallible> {
|
||||||
|
let host = req.headers().get(HOST);
|
||||||
|
let remote = match get_remote(host, &instances, &base_address).await {
|
||||||
|
Ok(remote) => remote,
|
||||||
|
Err(e) => {
|
||||||
|
return Ok(Response::builder()
|
||||||
|
.status(StatusCode::INTERNAL_SERVER_ERROR)
|
||||||
|
.body(e.into())
|
||||||
|
.unwrap())
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let forward = format!("http://{}", remote);
|
||||||
|
let client = hyper::Client::builder().build_http();
|
||||||
|
match hyper_reverse_proxy::call(client_ip, &forward, req, &client).await {
|
||||||
|
Ok(response) => Ok(response),
|
||||||
|
Err(_error) => Ok(Response::builder()
|
||||||
|
.status(StatusCode::INTERNAL_SERVER_ERROR)
|
||||||
|
.body(Body::empty())
|
||||||
|
.unwrap()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue