Compare commits
No commits in common. "c76d7318f033382fbbdca381b97ed266a83071f5" and "e416a766682af3b78538854da09eee62baaf3762" have entirely different histories.
c76d7318f0
...
e416a76668
296
Cargo.lock
generated
296
Cargo.lock
generated
@ -9,7 +9,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "453e534d4f46dcdddd7aa8619e9a664e153f34383d14710db0b0d76c2964db89"
|
checksum = "453e534d4f46dcdddd7aa8619e9a664e153f34383d14710db0b0d76c2964db89"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.13.1",
|
"base64 0.13.1",
|
||||||
"hyper 0.14.26",
|
"hyper",
|
||||||
"openssl",
|
"openssl",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"serde",
|
"serde",
|
||||||
@ -138,12 +138,6 @@ version = "1.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "awaitgroup"
|
|
||||||
version = "0.7.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a872ceb3db05a391fbe7cf8eba07a1239b2d946eee66f9e942be9bff06206302"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "backtrace"
|
name = "backtrace"
|
||||||
version = "0.3.69"
|
version = "0.3.69"
|
||||||
@ -407,9 +401,9 @@ checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "digest"
|
name = "digest"
|
||||||
version = "0.10.7"
|
version = "0.10.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"block-buffer",
|
"block-buffer",
|
||||||
"crypto-common",
|
"crypto-common",
|
||||||
@ -421,7 +415,6 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"acme2",
|
"acme2",
|
||||||
"async-compression",
|
"async-compression",
|
||||||
"awaitgroup",
|
|
||||||
"bytes",
|
"bytes",
|
||||||
"clap",
|
"clap",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
@ -431,12 +424,10 @@ dependencies = [
|
|||||||
"gix-object",
|
"gix-object",
|
||||||
"handlebars",
|
"handlebars",
|
||||||
"hex",
|
"hex",
|
||||||
"http 1.0.0",
|
"http",
|
||||||
"http-body 1.0.0",
|
"hyper",
|
||||||
"http-body-util",
|
|
||||||
"hyper 1.2.0",
|
|
||||||
"hyper-reverse-proxy",
|
"hyper-reverse-proxy",
|
||||||
"hyper-util",
|
"hyper-trust-dns",
|
||||||
"log",
|
"log",
|
||||||
"mime_guess",
|
"mime_guess",
|
||||||
"mockall",
|
"mockall",
|
||||||
@ -445,7 +436,7 @@ dependencies = [
|
|||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"rust-embed",
|
"rust-embed",
|
||||||
"rustls",
|
"rustls 0.21.10",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_urlencoded",
|
"serde_urlencoded",
|
||||||
@ -455,8 +446,9 @@ dependencies = [
|
|||||||
"signal-hook",
|
"signal-hook",
|
||||||
"tempdir",
|
"tempdir",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
"tls-listener",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-rustls",
|
"tokio-rustls 0.24.1",
|
||||||
"tokio-util",
|
"tokio-util",
|
||||||
"trust-dns-client",
|
"trust-dns-client",
|
||||||
]
|
]
|
||||||
@ -848,7 +840,7 @@ dependencies = [
|
|||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-sink",
|
"futures-sink",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"http 0.2.9",
|
"http",
|
||||||
"indexmap 1.9.3",
|
"indexmap 1.9.3",
|
||||||
"slab",
|
"slab",
|
||||||
"tokio",
|
"tokio",
|
||||||
@ -856,25 +848,6 @@ dependencies = [
|
|||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "h2"
|
|
||||||
version = "0.4.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "31d030e59af851932b72ceebadf4a2b5986dba4c3b99dd2493f8273a0f151943"
|
|
||||||
dependencies = [
|
|
||||||
"bytes",
|
|
||||||
"fnv",
|
|
||||||
"futures-core",
|
|
||||||
"futures-sink",
|
|
||||||
"futures-util",
|
|
||||||
"http 1.0.0",
|
|
||||||
"indexmap 2.0.0",
|
|
||||||
"slab",
|
|
||||||
"tokio",
|
|
||||||
"tokio-util",
|
|
||||||
"tracing",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "handlebars"
|
name = "handlebars"
|
||||||
version = "4.3.7"
|
version = "4.3.7"
|
||||||
@ -940,17 +913,6 @@ dependencies = [
|
|||||||
"itoa",
|
"itoa",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "http"
|
|
||||||
version = "1.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b32afd38673a8016f7c9ae69e5af41a58f81b1d31689040f2f1959594ce194ea"
|
|
||||||
dependencies = [
|
|
||||||
"bytes",
|
|
||||||
"fnv",
|
|
||||||
"itoa",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "http-body"
|
name = "http-body"
|
||||||
version = "0.4.5"
|
version = "0.4.5"
|
||||||
@ -958,30 +920,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1"
|
checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"http 0.2.9",
|
"http",
|
||||||
"pin-project-lite",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "http-body"
|
|
||||||
version = "1.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643"
|
|
||||||
dependencies = [
|
|
||||||
"bytes",
|
|
||||||
"http 1.0.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "http-body-util"
|
|
||||||
version = "0.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "41cb79eb393015dadd30fc252023adb0b2400a0caee0fa2a077e6e21a551e840"
|
|
||||||
dependencies = [
|
|
||||||
"bytes",
|
|
||||||
"futures-util",
|
|
||||||
"http 1.0.0",
|
|
||||||
"http-body 1.0.0",
|
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -1013,9 +952,9 @@ dependencies = [
|
|||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"h2 0.3.18",
|
"h2",
|
||||||
"http 0.2.9",
|
"http",
|
||||||
"http-body 0.4.5",
|
"http-body",
|
||||||
"httparse",
|
"httparse",
|
||||||
"httpdate",
|
"httpdate",
|
||||||
"itoa",
|
"itoa",
|
||||||
@ -1027,39 +966,31 @@ dependencies = [
|
|||||||
"want",
|
"want",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "hyper"
|
|
||||||
version = "1.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a"
|
|
||||||
dependencies = [
|
|
||||||
"bytes",
|
|
||||||
"futures-channel",
|
|
||||||
"futures-util",
|
|
||||||
"h2 0.4.2",
|
|
||||||
"http 1.0.0",
|
|
||||||
"http-body 1.0.0",
|
|
||||||
"httparse",
|
|
||||||
"httpdate",
|
|
||||||
"itoa",
|
|
||||||
"pin-project-lite",
|
|
||||||
"smallvec",
|
|
||||||
"tokio",
|
|
||||||
"want",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper-reverse-proxy"
|
name = "hyper-reverse-proxy"
|
||||||
version = "0.5.2-dev"
|
version = "0.5.2-dev"
|
||||||
source = "git+https://code.betamike.com/micropelago/hyper-reverse-proxy.git?branch=master#1dc4618994a5e9bc5de2083b911b1b08da7c081f"
|
source = "git+https://code.betamike.com/micropelago/hyper-reverse-proxy.git?branch=dont-set-host-header#9f4b94724f9b164d2e2d08607780d5e85f53368e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hyper 1.2.0",
|
"hyper",
|
||||||
"hyper-util",
|
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hyper-rustls"
|
||||||
|
version = "0.23.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1788965e61b367cd03a62950836d5cd41560c3577d90e40e0819373194d1661c"
|
||||||
|
dependencies = [
|
||||||
|
"http",
|
||||||
|
"hyper",
|
||||||
|
"rustls 0.20.9",
|
||||||
|
"tokio",
|
||||||
|
"tokio-rustls 0.23.4",
|
||||||
|
"webpki-roots 0.22.6",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper-rustls"
|
name = "hyper-rustls"
|
||||||
version = "0.24.1"
|
version = "0.24.1"
|
||||||
@ -1067,11 +998,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97"
|
checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"http 0.2.9",
|
"http",
|
||||||
"hyper 0.14.26",
|
"hyper",
|
||||||
"rustls",
|
"rustls 0.21.10",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-rustls",
|
"tokio-rustls 0.24.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1081,30 +1012,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905"
|
checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"hyper 0.14.26",
|
"hyper",
|
||||||
"native-tls",
|
"native-tls",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-native-tls",
|
"tokio-native-tls",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper-util"
|
name = "hyper-trust-dns"
|
||||||
version = "0.1.3"
|
version = "0.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa"
|
checksum = "0deaf08b5c5409c0c74011f696a82bdadae4c6d70b7a71edf8378b29bdd840bd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"hyper",
|
||||||
"futures-channel",
|
"hyper-rustls 0.23.2",
|
||||||
"futures-util",
|
|
||||||
"http 1.0.0",
|
|
||||||
"http-body 1.0.0",
|
|
||||||
"hyper 1.2.0",
|
|
||||||
"pin-project-lite",
|
|
||||||
"socket2 0.5.5",
|
|
||||||
"tokio",
|
"tokio",
|
||||||
"tower",
|
"trust-dns-resolver",
|
||||||
"tower-service",
|
|
||||||
"tracing",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1265,6 +1188,12 @@ version = "0.2.150"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
|
checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "linked-hash-map"
|
||||||
|
version = "0.5.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linux-raw-sys"
|
name = "linux-raw-sys"
|
||||||
version = "0.3.6"
|
version = "0.3.6"
|
||||||
@ -1287,6 +1216,15 @@ version = "0.4.19"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"
|
checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lru-cache"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c"
|
||||||
|
dependencies = [
|
||||||
|
"linked-hash-map",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "matches"
|
name = "matches"
|
||||||
version = "0.1.10"
|
version = "0.1.10"
|
||||||
@ -1843,11 +1781,11 @@ dependencies = [
|
|||||||
"encoding_rs",
|
"encoding_rs",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"h2 0.3.18",
|
"h2",
|
||||||
"http 0.2.9",
|
"http",
|
||||||
"http-body 0.4.5",
|
"http-body",
|
||||||
"hyper 0.14.26",
|
"hyper",
|
||||||
"hyper-rustls",
|
"hyper-rustls 0.24.1",
|
||||||
"hyper-tls",
|
"hyper-tls",
|
||||||
"ipnet",
|
"ipnet",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
@ -1857,7 +1795,7 @@ dependencies = [
|
|||||||
"once_cell",
|
"once_cell",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"rustls",
|
"rustls 0.21.10",
|
||||||
"rustls-pemfile",
|
"rustls-pemfile",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
@ -1865,7 +1803,7 @@ dependencies = [
|
|||||||
"system-configuration",
|
"system-configuration",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-native-tls",
|
"tokio-native-tls",
|
||||||
"tokio-rustls",
|
"tokio-rustls 0.24.1",
|
||||||
"tokio-util",
|
"tokio-util",
|
||||||
"tower-service",
|
"tower-service",
|
||||||
"url",
|
"url",
|
||||||
@ -1873,7 +1811,7 @@ dependencies = [
|
|||||||
"wasm-bindgen-futures",
|
"wasm-bindgen-futures",
|
||||||
"wasm-streams",
|
"wasm-streams",
|
||||||
"web-sys",
|
"web-sys",
|
||||||
"webpki-roots",
|
"webpki-roots 0.25.3",
|
||||||
"winreg",
|
"winreg",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -1960,6 +1898,17 @@ dependencies = [
|
|||||||
"windows-sys 0.48.0",
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustls"
|
||||||
|
version = "0.20.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1b80e3dec595989ea8510028f30c408a4630db12c9cbb8de34203b89d6577e99"
|
||||||
|
dependencies = [
|
||||||
|
"ring 0.16.20",
|
||||||
|
"sct",
|
||||||
|
"webpki",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustls"
|
name = "rustls"
|
||||||
version = "0.21.10"
|
version = "0.21.10"
|
||||||
@ -2146,9 +2095,9 @@ checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sha2"
|
name = "sha2"
|
||||||
version = "0.10.8"
|
version = "0.10.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
|
checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"cpufeatures",
|
"cpufeatures",
|
||||||
@ -2185,9 +2134,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smallvec"
|
name = "smallvec"
|
||||||
version = "1.13.1"
|
version = "1.10.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7"
|
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "socket2"
|
name = "socket2"
|
||||||
@ -2386,6 +2335,20 @@ version = "0.1.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tls-listener"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "81294c017957a1a69794f506723519255879e15a870507faf45dfed288b763dd"
|
||||||
|
dependencies = [
|
||||||
|
"futures-util",
|
||||||
|
"hyper",
|
||||||
|
"pin-project-lite",
|
||||||
|
"thiserror",
|
||||||
|
"tokio",
|
||||||
|
"tokio-rustls 0.24.1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.34.0"
|
version = "1.34.0"
|
||||||
@ -2426,12 +2389,23 @@ dependencies = [
|
|||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-rustls"
|
||||||
|
version = "0.23.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59"
|
||||||
|
dependencies = [
|
||||||
|
"rustls 0.20.9",
|
||||||
|
"tokio",
|
||||||
|
"webpki",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-rustls"
|
name = "tokio-rustls"
|
||||||
version = "0.24.1"
|
version = "0.24.1"
|
||||||
source = "git+https://code.betamike.com/micropelago/tokio-rustls.git?branch=start-handshake-into-inner#3d462a1d97836cdb0600f0bc69c5e3b3310f6d8c"
|
source = "git+https://code.betamike.com/micropelago/tokio-rustls.git?branch=start-handshake-into-inner#3d462a1d97836cdb0600f0bc69c5e3b3310f6d8c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rustls",
|
"rustls 0.21.10",
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -2449,28 +2423,6 @@ dependencies = [
|
|||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tower"
|
|
||||||
version = "0.4.13"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
|
|
||||||
dependencies = [
|
|
||||||
"futures-core",
|
|
||||||
"futures-util",
|
|
||||||
"pin-project",
|
|
||||||
"pin-project-lite",
|
|
||||||
"tokio",
|
|
||||||
"tower-layer",
|
|
||||||
"tower-service",
|
|
||||||
"tracing",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tower-layer"
|
|
||||||
version = "0.3.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tower-service"
|
name = "tower-service"
|
||||||
version = "0.3.2"
|
version = "0.3.2"
|
||||||
@ -2484,7 +2436,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
|
checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"log",
|
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"tracing-attributes",
|
"tracing-attributes",
|
||||||
"tracing-core",
|
"tracing-core",
|
||||||
@ -2565,6 +2516,24 @@ dependencies = [
|
|||||||
"url",
|
"url",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "trust-dns-resolver"
|
||||||
|
version = "0.22.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "aff21aa4dcefb0a1afbfac26deb0adc93888c7d295fb63ab273ef276ba2b7cfe"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"futures-util",
|
||||||
|
"lazy_static",
|
||||||
|
"lru-cache",
|
||||||
|
"parking_lot",
|
||||||
|
"smallvec",
|
||||||
|
"thiserror",
|
||||||
|
"tokio",
|
||||||
|
"tracing",
|
||||||
|
"trust-dns-proto",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "try-lock"
|
name = "try-lock"
|
||||||
version = "0.2.4"
|
version = "0.2.4"
|
||||||
@ -2775,6 +2744,25 @@ 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 0.16.20",
|
||||||
|
"untrusted 0.7.1",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "webpki-roots"
|
||||||
|
version = "0.22.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87"
|
||||||
|
dependencies = [
|
||||||
|
"webpki",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webpki-roots"
|
name = "webpki-roots"
|
||||||
version = "0.25.3"
|
version = "0.25.3"
|
||||||
|
15
Cargo.toml
15
Cargo.toml
@ -23,8 +23,8 @@ clap = { version = "4.2.7", features = ["derive", "env"] }
|
|||||||
handlebars = { version = "4.3.7", features = [ "rust-embed" ]}
|
handlebars = { version = "4.3.7", features = [ "rust-embed" ]}
|
||||||
rust-embed = "6.6.1"
|
rust-embed = "6.6.1"
|
||||||
mime_guess = "2.0.4"
|
mime_guess = "2.0.4"
|
||||||
hyper = { version = "1.2.0", features = ["server", "client", "http1", "http2"] }
|
hyper = { version = "0.14.26", features = [ "server", "stream" ]}
|
||||||
http = "1.0.0"
|
http = "0.2.9"
|
||||||
serde_urlencoded = "0.7.1"
|
serde_urlencoded = "0.7.1"
|
||||||
tokio-util = { version = "0.7.8", features = [ "io" ]}
|
tokio-util = { version = "0.7.8", features = [ "io" ]}
|
||||||
acme2 = "0.5.1"
|
acme2 = "0.5.1"
|
||||||
@ -32,6 +32,7 @@ openssl = "0.10.52"
|
|||||||
rustls = "0.21.1"
|
rustls = "0.21.1"
|
||||||
pem = "2.0.1"
|
pem = "2.0.1"
|
||||||
serde_with = "3.0.0"
|
serde_with = "3.0.0"
|
||||||
|
tls-listener = { version = "0.7.0", features = [ "rustls", "hyper-h1" ]}
|
||||||
tokio-rustls = "0.24.0"
|
tokio-rustls = "0.24.0"
|
||||||
log = "0.4.19"
|
log = "0.4.19"
|
||||||
env_logger = "0.10.0"
|
env_logger = "0.10.0"
|
||||||
@ -40,20 +41,14 @@ rand = "0.8.5"
|
|||||||
hyper-reverse-proxy = "0.5.2-dev"
|
hyper-reverse-proxy = "0.5.2-dev"
|
||||||
gemini = "0.0.5"
|
gemini = "0.0.5"
|
||||||
bytes = "1.4.0"
|
bytes = "1.4.0"
|
||||||
|
hyper-trust-dns = "0.5.0"
|
||||||
gix-hash = "0.14.1"
|
gix-hash = "0.14.1"
|
||||||
reqwest = { version = "0.11.23", features = ["gzip", "deflate", "stream"] }
|
reqwest = { version = "0.11.23", features = ["gzip", "deflate", "stream"] }
|
||||||
gix-object = "0.41.0"
|
gix-object = "0.41.0"
|
||||||
async-compression = { version = "0.4.6", features = ["tokio", "deflate", "zlib"] }
|
async-compression = { version = "0.4.6", features = ["tokio", "deflate", "zlib"] }
|
||||||
hyper-util = { version = "0.1.3", features = ["server", "http1", "http2", "tokio"] }
|
|
||||||
http-body-util = "0.1.0"
|
|
||||||
http-body = "1.0.0"
|
|
||||||
awaitgroup = "0.7.0"
|
|
||||||
|
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
|
|
||||||
# The micropelago fork of tokio-rustls allows for gemini proxying
|
# The micropelago fork of tokio-rustls allows for gemini proxying
|
||||||
tokio-rustls = { git = "https://code.betamike.com/micropelago/tokio-rustls.git", branch = "start-handshake-into-inner" }
|
tokio-rustls = { git = "https://code.betamike.com/micropelago/tokio-rustls.git", branch = "start-handshake-into-inner" }
|
||||||
|
hyper-reverse-proxy = { git = "https://code.betamike.com/micropelago/hyper-reverse-proxy.git", branch = "dont-set-host-header" }
|
||||||
# The micropelago fork of hyper-reverse-proxy supports hyper v1, and fixes some
|
|
||||||
# bugs from upstream (which appears to be unmaintained).
|
|
||||||
hyper-reverse-proxy = { git = "https://code.betamike.com/micropelago/hyper-reverse-proxy.git", branch = "master" }
|
|
||||||
|
38
flake.lock
38
flake.lock
@ -2,17 +2,15 @@
|
|||||||
"nodes": {
|
"nodes": {
|
||||||
"fenix": {
|
"fenix": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": [
|
"nixpkgs": "nixpkgs",
|
||||||
"nixpkgs"
|
|
||||||
],
|
|
||||||
"rust-analyzer-src": "rust-analyzer-src"
|
"rust-analyzer-src": "rust-analyzer-src"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1708928609,
|
"lastModified": 1699770036,
|
||||||
"narHash": "sha256-LcXC2NP/TzHMmJThZGG1e+7rht5HeuZK5WOirIDg+lU=",
|
"narHash": "sha256-bZmI7ytPAYLpyFNgj5xirDkKuAniOkj1xHdv5aIJ5GM=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "fenix",
|
"repo": "fenix",
|
||||||
"rev": "e928fb6b5179ebd032c19afac5c461ccc0b6de55",
|
"rev": "81ab0b4f7ae9ebb57daa0edf119c4891806e4d3a",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -23,7 +21,7 @@
|
|||||||
},
|
},
|
||||||
"naersk": {
|
"naersk": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": "nixpkgs"
|
"nixpkgs": "nixpkgs_2"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1690373729,
|
"lastModified": 1690373729,
|
||||||
@ -41,6 +39,22 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1699099776,
|
||||||
|
"narHash": "sha256-X09iKJ27mGsGambGfkKzqvw5esP1L/Rf8H3u3fCqIiU=",
|
||||||
|
"owner": "nixos",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "85f1ba3e51676fa8cc604a3d863d729026a6b8eb",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nixos",
|
||||||
|
"ref": "nixos-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs_2": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1691003216,
|
"lastModified": 1691003216,
|
||||||
"narHash": "sha256-Qq/MPkhS12Bl0X060pPvX3v9ac3f2rRQfHjjozPh/Qs=",
|
"narHash": "sha256-Qq/MPkhS12Bl0X060pPvX3v9ac3f2rRQfHjjozPh/Qs=",
|
||||||
@ -54,7 +68,7 @@
|
|||||||
"type": "indirect"
|
"type": "indirect"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs_2": {
|
"nixpkgs_3": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1688392541,
|
"lastModified": 1688392541,
|
||||||
"narHash": "sha256-lHrKvEkCPTUO+7tPfjIcb7Trk6k31rz18vkyqmkeJfY=",
|
"narHash": "sha256-lHrKvEkCPTUO+7tPfjIcb7Trk6k31rz18vkyqmkeJfY=",
|
||||||
@ -74,17 +88,17 @@
|
|||||||
"inputs": {
|
"inputs": {
|
||||||
"fenix": "fenix",
|
"fenix": "fenix",
|
||||||
"naersk": "naersk",
|
"naersk": "naersk",
|
||||||
"nixpkgs": "nixpkgs_2"
|
"nixpkgs": "nixpkgs_3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rust-analyzer-src": {
|
"rust-analyzer-src": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1708878562,
|
"lastModified": 1699715108,
|
||||||
"narHash": "sha256-IBHMNEe3lspVdIzjpM2OVZiBFmFw1DKtdgVN5G41pRc=",
|
"narHash": "sha256-yPozsobJU55gj+szgo4Lpcg1lHvGQYAT6Y4MrC80mWE=",
|
||||||
"owner": "rust-lang",
|
"owner": "rust-lang",
|
||||||
"repo": "rust-analyzer",
|
"repo": "rust-analyzer",
|
||||||
"rev": "5346002d07d09badaf37949bec68012d963d61fc",
|
"rev": "5fcf5289e726785d20d3aa4d13d90a43ed248e83",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
{
|
{
|
||||||
inputs = {
|
inputs = {
|
||||||
fenix.url = "github:nix-community/fenix";
|
fenix.url = "github:nix-community/fenix";
|
||||||
fenix.inputs.nixpkgs.follows = "nixpkgs";
|
|
||||||
naersk.url = "github:nix-community/naersk/master";
|
naersk.url = "github:nix-community/naersk/master";
|
||||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-22.11";
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-22.11";
|
||||||
};
|
};
|
||||||
@ -120,8 +119,9 @@
|
|||||||
# TODO I'd prefer to use the toolchain file
|
# TODO I'd prefer to use the toolchain file
|
||||||
# https://github.com/nix-community/fenix/issues/123
|
# https://github.com/nix-community/fenix/issues/123
|
||||||
fenixToolchain = fenixTarget: (builtins.getAttr "toolchainOf" fenixTarget) {
|
fenixToolchain = fenixTarget: (builtins.getAttr "toolchainOf" fenixTarget) {
|
||||||
channel = "1.76.0";
|
channel = "nightly";
|
||||||
sha256 = "sha256-e4mlaJehWBymYxJGgnbuCObVlqMlQSilZ8FljG9zPHY=";
|
date = "2023-07-23";
|
||||||
|
sha256 = "sha256-LU4C/i+maIOqBZagUaXpFyWZyOVfQ3Ah5/JTz7v6CG4=";
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
fenixPkgs.combine [
|
fenixPkgs.combine [
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[toolchain]
|
[toolchain]
|
||||||
channel = "1.76.0"
|
channel = "nightly-2023-07-23"
|
||||||
components = [ "rustfmt", "rustc-dev", "clippy", "cargo", "rust-std" ]
|
components = [ "rustfmt", "rustc-dev", "clippy", "cargo" ]
|
||||||
targets = [
|
targets = [
|
||||||
"x86_64-unknown-linux-musl",
|
"x86_64-unknown-linux-musl",
|
||||||
"i686-unknown-linux-musl",
|
"i686-unknown-linux-musl",
|
||||||
|
@ -136,11 +136,10 @@ impl Manager for ManagerImpl {
|
|||||||
let thirty_days = openssl::asn1::Asn1Time::days_from_now(30)
|
let thirty_days = openssl::asn1::Asn1Time::days_from_now(30)
|
||||||
.expect("parsed thirty days from now as Asn1Time");
|
.expect("parsed thirty days from now as Asn1Time");
|
||||||
|
|
||||||
let cert_with_soonest_not_after = util::try_collect(
|
let cert_with_soonest_not_after = certs
|
||||||
certs
|
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|cert| openssl::x509::X509::try_from(&cert)),
|
.map(|cert| openssl::x509::X509::try_from(&cert))
|
||||||
)
|
.try_collect::<Vec<openssl::x509::X509>>()
|
||||||
.or_unexpected_while("parsing x509 certs")?
|
.or_unexpected_while("parsing x509 certs")?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.reduce(|a, b| if a.not_after() < b.not_after() { a } else { b })
|
.reduce(|a, b| if a.not_after() < b.not_after() { a } else { b })
|
||||||
@ -305,8 +304,7 @@ impl Manager for ManagerImpl {
|
|||||||
|
|
||||||
// Download the certificate, and panic if it doesn't exist.
|
// Download the certificate, and panic if it doesn't exist.
|
||||||
log::info!("Fetching certificate for domain {}", domain.as_str());
|
log::info!("Fetching certificate for domain {}", domain.as_str());
|
||||||
let certs = util::try_collect(
|
let certs = order
|
||||||
order
|
|
||||||
.certificate()
|
.certificate()
|
||||||
.await
|
.await
|
||||||
.or_unexpected_while("fetching certificate")?
|
.or_unexpected_while("fetching certificate")?
|
||||||
@ -314,8 +312,8 @@ impl Manager for ManagerImpl {
|
|||||||
"expected the order to return a certificate",
|
"expected the order to return a certificate",
|
||||||
))?
|
))?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|cert| Certificate::try_from(cert.as_ref())),
|
.map(|cert| Certificate::try_from(cert.as_ref()))
|
||||||
)
|
.try_collect::<Vec<Certificate>>()
|
||||||
.or_unexpected_while("parsing certificate")?;
|
.or_unexpected_while("parsing certificate")?;
|
||||||
|
|
||||||
if certs.len() <= 1 {
|
if certs.len() <= 1 {
|
||||||
|
@ -6,9 +6,13 @@ fn addr_from_url(
|
|||||||
expected_scheme: &str,
|
expected_scheme: &str,
|
||||||
default_port: u16,
|
default_port: u16,
|
||||||
) -> unexpected::Result<String> {
|
) -> unexpected::Result<String> {
|
||||||
let parsed: http::Uri = url.parse().or_unexpected_while("could not parse as url")?;
|
let parsed: http::Uri = url
|
||||||
|
.parse()
|
||||||
|
.map_unexpected_while(|| format!("could not parse as url"))?;
|
||||||
|
|
||||||
let scheme = parsed.scheme().or_unexpected_while("scheme is missing")?;
|
let scheme = parsed
|
||||||
|
.scheme()
|
||||||
|
.map_unexpected_while(|| format!("scheme is missing"))?;
|
||||||
|
|
||||||
if scheme != expected_scheme {
|
if scheme != expected_scheme {
|
||||||
return Err(unexpected::Error::from(
|
return Err(unexpected::Error::from(
|
||||||
|
@ -4,15 +4,6 @@ use crate::{origin, task_stack, util};
|
|||||||
|
|
||||||
use std::sync;
|
use std::sync;
|
||||||
|
|
||||||
fn collect_into<I, V>(into: &mut Vec<V>, iter: I)
|
|
||||||
where
|
|
||||||
I: std::iter::Iterator<Item = V>,
|
|
||||||
{
|
|
||||||
for v in iter {
|
|
||||||
into.push(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum GetSettingsResult {
|
pub enum GetSettingsResult {
|
||||||
Stored(domain::Settings),
|
Stored(domain::Settings),
|
||||||
Builtin(domain::config::ConfigBuiltinDomain),
|
Builtin(domain::config::ConfigBuiltinDomain),
|
||||||
@ -486,27 +477,23 @@ impl Manager for ManagerImpl {
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
collect_into(
|
|
||||||
&mut res,
|
|
||||||
self.config
|
self.config
|
||||||
.builtin_domains
|
.builtin_domains
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(domain, config)| ManagedDomain {
|
.map(|(domain, config)| ManagedDomain {
|
||||||
domain: domain.clone(),
|
domain: domain.clone(),
|
||||||
public: config.public,
|
public: config.public,
|
||||||
}),
|
})
|
||||||
);
|
.collect_into(&mut res);
|
||||||
|
|
||||||
collect_into(
|
|
||||||
&mut res,
|
|
||||||
self.config
|
self.config
|
||||||
.proxied_domains
|
.proxied_domains
|
||||||
.keys()
|
.keys()
|
||||||
.map(|domain| ManagedDomain {
|
.map(|domain| ManagedDomain {
|
||||||
domain: domain.clone(),
|
domain: domain.clone(),
|
||||||
public: false,
|
public: false,
|
||||||
}),
|
})
|
||||||
);
|
.collect_into(&mut res);
|
||||||
|
|
||||||
if let Some(ref interface_domain) = self.config.interface_domain {
|
if let Some(ref interface_domain) = self.config.interface_domain {
|
||||||
res.push(ManagedDomain {
|
res.push(ManagedDomain {
|
||||||
@ -515,16 +502,14 @@ impl Manager for ManagerImpl {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
collect_into(
|
|
||||||
&mut res,
|
|
||||||
self.config
|
self.config
|
||||||
.external_domains
|
.external_domains
|
||||||
.keys()
|
.keys()
|
||||||
.map(|domain| ManagedDomain {
|
.map(|domain| ManagedDomain {
|
||||||
domain: domain.clone(),
|
domain: domain.clone(),
|
||||||
public: false,
|
public: false,
|
||||||
}),
|
})
|
||||||
);
|
.collect_into(&mut res);
|
||||||
|
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,9 @@ impl Store for FSStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn all_domains(&self) -> unexpected::Result<Vec<domain::Name>> {
|
fn all_domains(&self) -> unexpected::Result<Vec<domain::Name>> {
|
||||||
let domains = fs::read_dir(&self.dir_path).or_unexpected()?.map(
|
fs::read_dir(&self.dir_path)
|
||||||
|
.or_unexpected()?
|
||||||
|
.map(
|
||||||
|dir_entry_res: io::Result<fs::DirEntry>| -> unexpected::Result<domain::Name> {
|
|dir_entry_res: io::Result<fs::DirEntry>| -> unexpected::Result<domain::Name> {
|
||||||
let domain = dir_entry_res.or_unexpected()?.file_name();
|
let domain = dir_entry_res.or_unexpected()?.file_name();
|
||||||
let domain = domain.to_str().ok_or(unexpected::Error::from(
|
let domain = domain.to_str().ok_or(unexpected::Error::from(
|
||||||
@ -83,9 +85,8 @@ impl Store for FSStore {
|
|||||||
.parse()
|
.parse()
|
||||||
.map_unexpected_while(|| format!("parsing {domain} as domain name"))
|
.map_unexpected_while(|| format!("parsing {domain} as domain name"))
|
||||||
},
|
},
|
||||||
);
|
)
|
||||||
|
.try_collect()
|
||||||
crate::util::try_collect(domains.into_iter())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
#![feature(result_option_inspect)]
|
||||||
|
#![feature(iterator_try_collect)]
|
||||||
|
#![feature(iter_collect_into)]
|
||||||
|
|
||||||
pub mod config;
|
pub mod config;
|
||||||
pub mod domain;
|
pub mod domain;
|
||||||
pub mod origin;
|
pub mod origin;
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#![feature(trait_upcasting)]
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use std::path;
|
use std::path;
|
||||||
|
|
||||||
|
@ -13,9 +13,13 @@ pub struct GitUrl {
|
|||||||
impl std::str::FromStr for GitUrl {
|
impl std::str::FromStr for GitUrl {
|
||||||
type Err = unexpected::Error;
|
type Err = unexpected::Error;
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
let parsed: http::Uri = s.parse().or_unexpected_while("parsing as url")?;
|
let parsed: http::Uri = s
|
||||||
|
.parse()
|
||||||
|
.map_unexpected_while(|| format!("parsing as url"))?;
|
||||||
|
|
||||||
let scheme = parsed.scheme().or_unexpected_while("extracting scheme")?;
|
let scheme = parsed
|
||||||
|
.scheme()
|
||||||
|
.map_unexpected_while(|| format!("extracting scheme"))?;
|
||||||
|
|
||||||
if scheme != "http" && scheme != "https" {
|
if scheme != "http" && scheme != "https" {
|
||||||
return Err(unexpected::Error::from(
|
return Err(unexpected::Error::from(
|
||||||
|
@ -6,39 +6,15 @@ mod util;
|
|||||||
|
|
||||||
pub use config::*;
|
pub use config::*;
|
||||||
|
|
||||||
use std::{future, io, net, sync};
|
use http::request::Parts;
|
||||||
|
use hyper::{Body, Method, Request, Response};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use std::{future, net, sync};
|
||||||
|
|
||||||
use crate::error::unexpected::{self, Mappable};
|
use crate::error::unexpected::{self, Mappable};
|
||||||
use crate::{domain, service, task_stack};
|
use crate::{domain, service, task_stack};
|
||||||
|
|
||||||
use http_body_util::combinators::UnsyncBoxBody as BoxBody;
|
|
||||||
use hyper::{
|
|
||||||
body::{Body, Incoming as RequestBody},
|
|
||||||
Method,
|
|
||||||
};
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
type Request = hyper::Request<RequestBody>;
|
|
||||||
pub type Response = hyper::Response<BoxBody<bytes::Bytes, io::Error>>;
|
|
||||||
|
|
||||||
fn bytes_body(b: bytes::Bytes) -> impl Body<Data = bytes::Bytes, Error = io::Error> {
|
|
||||||
use http_body_util::BodyExt;
|
|
||||||
http_body_util::Full::new(b).map_err(io::Error::other)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn empty_body() -> impl Body<Data = bytes::Bytes, Error = io::Error> {
|
|
||||||
use http_body_util::BodyExt;
|
|
||||||
http_body_util::Empty::<bytes::Bytes>::new().map_err(io::Error::other)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn stream_body<S>(s: S) -> impl Body<Data = bytes::Bytes, Error = io::Error>
|
|
||||||
where
|
|
||||||
S: futures::stream::Stream<Item = io::Result<bytes::Bytes>>,
|
|
||||||
{
|
|
||||||
use futures::stream::TryStreamExt;
|
|
||||||
http_body_util::StreamBody::new(s.map_ok(http_body::Frame::data))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
struct BasePresenter<'a, T> {
|
struct BasePresenter<'a, T> {
|
||||||
page_name: &'a str,
|
page_name: &'a str,
|
||||||
@ -106,18 +82,27 @@ impl Service {
|
|||||||
self.config.http.https_addr.is_some()
|
self.config.http.https_addr.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serve<B>(&self, status_code: u16, path: &str, body: B) -> Response
|
fn serve(&self, status_code: u16, path: &str, body: Body) -> Response<Body> {
|
||||||
where
|
match Response::builder()
|
||||||
B: Body<Data = bytes::Bytes, Error = io::Error> + Send + 'static,
|
|
||||||
{
|
|
||||||
hyper::Response::builder()
|
|
||||||
.status(status_code)
|
.status(status_code)
|
||||||
.header("Content-Type", service::guess_mime(path))
|
.header("Content-Type", service::guess_mime(path))
|
||||||
.body(BoxBody::new(body))
|
.body(body)
|
||||||
.unwrap_or_else(|err| panic!("failed to build {}: {}", path, err))
|
{
|
||||||
|
Ok(res) => res,
|
||||||
|
Err(err) => {
|
||||||
|
// if the status code was already a 500, don't try to render _another_ 500, it'll
|
||||||
|
// probably fail for the same reason. At this point something is incredibly wrong,
|
||||||
|
// just panic.
|
||||||
|
if status_code == 500 {
|
||||||
|
panic!("failed to build {}: {}", path, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render<T>(&self, status_code: u16, name: &str, value: T) -> Response
|
self.internal_error(format!("failed to build {}: {}", path, err).as_str())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render<T>(&self, status_code: u16, name: &str, value: T) -> Response<Body>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: Serialize,
|
||||||
{
|
{
|
||||||
@ -128,11 +113,11 @@ impl Service {
|
|||||||
..
|
..
|
||||||
}) => return self.render_error_page(404, "Static asset not found"),
|
}) => return self.render_error_page(404, "Static asset not found"),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
return self.render_error_page(500, format!("template error: {err}").as_str());
|
return self.render_error_page(500, format!("template error: {err}").as_str())
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.serve(status_code, name, bytes_body(rendered.into()))
|
self.serve(status_code, name, rendered.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn presenter_http_scheme(&self) -> &str {
|
fn presenter_http_scheme(&self) -> &str {
|
||||||
@ -142,7 +127,7 @@ impl Service {
|
|||||||
"http"
|
"http"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_error_page(&self, status_code: u16, e: &str) -> Response {
|
fn render_error_page(&self, status_code: u16, e: &str) -> Response<Body> {
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
struct Response<'a> {
|
struct Response<'a> {
|
||||||
error_msg: &'a str,
|
error_msg: &'a str,
|
||||||
@ -160,7 +145,7 @@ impl Service {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn internal_error(&self, e: &str) -> Response {
|
fn internal_error(&self, e: &str) -> Response<Body> {
|
||||||
log::error!("Internal error: {e}");
|
log::error!("Internal error: {e}");
|
||||||
self.render_error_page(
|
self.render_error_page(
|
||||||
500,
|
500,
|
||||||
@ -168,17 +153,20 @@ impl Service {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_redirect(&self, status_code: u16, target_uri: &str) -> Response {
|
fn render_redirect(&self, status_code: u16, target_uri: &str) -> Response<Body> {
|
||||||
hyper::Response::builder()
|
Response::builder()
|
||||||
.status(status_code)
|
.status(status_code)
|
||||||
.header("Location", target_uri.to_string())
|
.header("Location", target_uri.to_string())
|
||||||
.body(BoxBody::new(empty_body()))
|
.body(Body::empty())
|
||||||
.unwrap_or_else(|err| {
|
.unwrap_or_else(|err| {
|
||||||
panic!("failed to render {status_code} redirect to {target_uri}: {err}",)
|
self.internal_error(
|
||||||
|
format!("failed to render {status_code} redirect to {target_uri}: {err}",)
|
||||||
|
.as_str(),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn https_redirect(&self, domain: domain::Name, req: Request) -> Response {
|
fn https_redirect(&self, domain: domain::Name, req: Request<Body>) -> Response<Body> {
|
||||||
let https_addr = self.config.http.https_addr.unwrap();
|
let https_addr = self.config.http.https_addr.unwrap();
|
||||||
|
|
||||||
(|| {
|
(|| {
|
||||||
@ -210,7 +198,7 @@ impl Service {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_page<T>(&self, name: &str, data: T) -> Response
|
fn render_page<T>(&self, name: &str, data: T) -> Response<Body>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: Serialize,
|
||||||
{
|
{
|
||||||
@ -226,12 +214,12 @@ impl Service {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn serve_origin(&self, settings: domain::Settings, req: Request) -> Response {
|
async fn serve_origin(&self, settings: domain::Settings, req: Request<Body>) -> Response<Body> {
|
||||||
let path = service::append_index_to_path(req.uri().path(), "index.html");
|
let path = service::append_index_to_path(req.uri().path(), "index.html");
|
||||||
|
|
||||||
use domain::manager::GetFileError;
|
use domain::manager::GetFileError;
|
||||||
match self.domain_manager.get_file(&settings, &path).await {
|
match self.domain_manager.get_file(&settings, &path).await {
|
||||||
Ok(f) => self.serve(200, &path, stream_body(f.into_stream())),
|
Ok(f) => self.serve(200, &path, Body::wrap_stream(f.into_stream())),
|
||||||
Err(GetFileError::FileNotFound) => self.render_error_page(404, "File not found"),
|
Err(GetFileError::FileNotFound) => self.render_error_page(404, "File not found"),
|
||||||
Err(GetFileError::Unavailable) => self.render_error_page(502, "Content unavailable"),
|
Err(GetFileError::Unavailable) => self.render_error_page(502, "Content unavailable"),
|
||||||
Err(GetFileError::DescrNotSynced) => self.internal_error(
|
Err(GetFileError::DescrNotSynced) => self.internal_error(
|
||||||
@ -259,23 +247,22 @@ impl Service {
|
|||||||
|
|
||||||
async fn with_query_req<'a, F, In, Out>(
|
async fn with_query_req<'a, F, In, Out>(
|
||||||
&self,
|
&self,
|
||||||
req: &'a hyper::http::request::Parts,
|
req: &'a Parts,
|
||||||
body: RequestBody,
|
body: Body,
|
||||||
f: F,
|
f: F,
|
||||||
) -> Response
|
) -> Response<Body>
|
||||||
where
|
where
|
||||||
In: for<'d> Deserialize<'d>,
|
In: for<'d> Deserialize<'d>,
|
||||||
F: FnOnce(In) -> Out,
|
F: FnOnce(In) -> Out,
|
||||||
Out: future::Future<Output = Response>,
|
Out: future::Future<Output = Response<Body>>,
|
||||||
{
|
{
|
||||||
let res = match self.config.http.form_method {
|
let res = match self.config.http.form_method {
|
||||||
ConfigFormMethod::GET => {
|
ConfigFormMethod::GET => {
|
||||||
serde_urlencoded::from_str::<In>(req.uri.query().unwrap_or(""))
|
serde_urlencoded::from_str::<In>(req.uri.query().unwrap_or(""))
|
||||||
}
|
}
|
||||||
ConfigFormMethod::POST => {
|
ConfigFormMethod::POST => {
|
||||||
use http_body_util::BodyExt;
|
let body = match hyper::body::to_bytes(body).await {
|
||||||
let body = match body.collect().await {
|
Ok(bytes) => bytes.to_vec(),
|
||||||
Ok(res) => res.to_bytes(),
|
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return self.internal_error(format!("failed to read body: {e}").as_str())
|
return self.internal_error(format!("failed to read body: {e}").as_str())
|
||||||
}
|
}
|
||||||
@ -292,7 +279,7 @@ impl Service {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn domain(&self, args: DomainArgs) -> Response {
|
fn domain(&self, args: DomainArgs) -> Response<Body> {
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
struct Data {
|
struct Data {
|
||||||
domain: domain::Name,
|
domain: domain::Name,
|
||||||
@ -324,7 +311,7 @@ impl Service {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn domain_init(&self, args: DomainInitArgs) -> Response {
|
fn domain_init(&self, args: DomainInitArgs) -> Response<Body> {
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
struct Data<'a> {
|
struct Data<'a> {
|
||||||
domain: domain::Name,
|
domain: domain::Name,
|
||||||
@ -381,7 +368,7 @@ impl Service {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn domain_sync(&self, args: DomainSyncArgs) -> Response {
|
async fn domain_sync(&self, args: DomainSyncArgs) -> Response<Body> {
|
||||||
if args.passphrase != self.config.passphrase.as_str() {
|
if args.passphrase != self.config.passphrase.as_str() {
|
||||||
return self.render_error_page(401, "Incorrect passphrase");
|
return self.render_error_page(401, "Incorrect passphrase");
|
||||||
}
|
}
|
||||||
@ -464,7 +451,7 @@ impl Service {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn domains(&self) -> Response {
|
fn domains(&self) -> Response<Body> {
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
struct Response {
|
struct Response {
|
||||||
domains: Vec<String>,
|
domains: Vec<String>,
|
||||||
@ -486,7 +473,7 @@ impl Service {
|
|||||||
self.render_page("/domains.html", Response { domains })
|
self.render_page("/domains.html", Response { domains })
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn serve_interface(&self, req: Request) -> Response {
|
async fn serve_interface(&self, req: Request<Body>) -> Response<Body> {
|
||||||
let (req, body) = req.into_parts();
|
let (req, body) = req.into_parts();
|
||||||
let path = req.uri.path();
|
let path = req.uri.path();
|
||||||
|
|
||||||
@ -524,7 +511,7 @@ impl Service {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn domain_from_req(req: &Request) -> Option<domain::Name> {
|
fn domain_from_req(req: &Request<Body>) -> Option<domain::Name> {
|
||||||
let host_header = req
|
let host_header = req
|
||||||
.headers()
|
.headers()
|
||||||
.get("Host")
|
.get("Host")
|
||||||
@ -540,18 +527,12 @@ impl Service {
|
|||||||
async fn handle_request(
|
async fn handle_request(
|
||||||
&self,
|
&self,
|
||||||
client_ip: net::IpAddr,
|
client_ip: net::IpAddr,
|
||||||
req: Request,
|
req: Request<Body>,
|
||||||
req_is_https: bool,
|
req_is_https: bool,
|
||||||
) -> Response {
|
) -> Response<Body> {
|
||||||
let domain = match Self::domain_from_req(&req) {
|
let domain = match Self::domain_from_req(&req) {
|
||||||
Some(domain) => {
|
Some(domain) => domain,
|
||||||
log::debug!("[{client_ip}] Serving request to {domain}{}", req.uri());
|
None => return self.render_error_page(400, "Cannot serve page without domain"),
|
||||||
domain
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
log::debug!("[{client_ip}] Domain not found on request");
|
|
||||||
return self.render_error_page(400, "Cannot serve page without domain");
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let method = req.method();
|
let method = req.method();
|
||||||
@ -564,7 +545,7 @@ impl Service {
|
|||||||
let token = path.trim_start_matches("/.well-known/acme-challenge/");
|
let token = path.trim_start_matches("/.well-known/acme-challenge/");
|
||||||
|
|
||||||
if let Ok(key) = self.domain_manager.get_acme_http01_challenge_key(token) {
|
if let Ok(key) = self.domain_manager.get_acme_http01_challenge_key(token) {
|
||||||
return self.serve(200, "token.txt", bytes_body(key.into()));
|
return self.serve(200, "token.txt", key.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -574,7 +555,7 @@ impl Service {
|
|||||||
.domain_manager
|
.domain_manager
|
||||||
.get_domain_checker_challenge_token(&domain)
|
.get_domain_checker_challenge_token(&domain)
|
||||||
{
|
{
|
||||||
Ok(Some(token)) => return self.serve(200, "token.txt", bytes_body(token.into())),
|
Ok(Some(token)) => return self.serve(200, "token.txt", token.into()),
|
||||||
Ok(None) => return self.render_error_page(404, "Token not found"),
|
Ok(None) => return self.render_error_page(404, "Token not found"),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return self.internal_error(
|
return self.internal_error(
|
||||||
@ -612,12 +593,6 @@ impl Service {
|
|||||||
req_is_https,
|
req_is_https,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map(|res| {
|
|
||||||
res.map(|body| {
|
|
||||||
use http_body_util::BodyExt;
|
|
||||||
body.map_err(io::Error::other).boxed_unsync()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.unwrap_or_else(|e| {
|
.unwrap_or_else(|e| {
|
||||||
self.internal_error(
|
self.internal_error(
|
||||||
format!("serving {domain} via proxy {}: {e}", http_url.original_url)
|
format!("serving {domain} via proxy {}: {e}", http_url.original_url)
|
||||||
@ -655,32 +630,3 @@ fn strip_port(host: &str) -> &str {
|
|||||||
Some(i) => &host[..i],
|
Some(i) => &host[..i],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct HyperServiceImpl {
|
|
||||||
service: sync::Arc<Service>,
|
|
||||||
client_ip: net::IpAddr,
|
|
||||||
is_https: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl HyperServiceImpl {
|
|
||||||
pub fn new(service: sync::Arc<Service>, client_ip: net::IpAddr, is_https: bool) -> Self {
|
|
||||||
Self {
|
|
||||||
service,
|
|
||||||
client_ip,
|
|
||||||
is_https,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl hyper::service::Service<Request> for HyperServiceImpl {
|
|
||||||
type Response = Response;
|
|
||||||
type Error = std::io::Error;
|
|
||||||
type Future = crate::util::BoxFuture<'static, Result<Self::Response, Self::Error>>;
|
|
||||||
|
|
||||||
fn call(&self, req: Request) -> Self::Future {
|
|
||||||
let service = self.service.clone();
|
|
||||||
let client_ip = self.client_ip;
|
|
||||||
let is_https = self.is_https;
|
|
||||||
Box::pin(async move { Ok(service.handle_request(client_ip, req, is_https).await) })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,18 +1,16 @@
|
|||||||
use crate::error::unexpected;
|
use crate::error::unexpected;
|
||||||
use std::net;
|
use std::net;
|
||||||
|
|
||||||
use hyper::body::Incoming;
|
|
||||||
use hyper_reverse_proxy::ReverseProxy;
|
use hyper_reverse_proxy::ReverseProxy;
|
||||||
use hyper_util::client::legacy::connect::HttpConnector;
|
use hyper_trust_dns::{TrustDnsHttpConnector, TrustDnsResolver};
|
||||||
use hyper_util::rt::TokioExecutor;
|
|
||||||
|
|
||||||
fn proxy_client() -> &'static ReverseProxy<HttpConnector> {
|
fn proxy_client() -> &'static ReverseProxy<TrustDnsHttpConnector> {
|
||||||
use std::sync::OnceLock;
|
use std::sync::OnceLock;
|
||||||
static PROXY_CLIENT: OnceLock<ReverseProxy<HttpConnector>> = OnceLock::new();
|
static PROXY_CLIENT: OnceLock<ReverseProxy<TrustDnsHttpConnector>> = OnceLock::new();
|
||||||
PROXY_CLIENT.get_or_init(|| {
|
PROXY_CLIENT.get_or_init(|| {
|
||||||
ReverseProxy::new(
|
ReverseProxy::new(
|
||||||
hyper_util::client::legacy::Builder::new(TokioExecutor::new())
|
hyper::Client::builder()
|
||||||
.build::<_, Incoming>(HttpConnector::new()),
|
.build::<_, hyper::Body>(TrustDnsResolver::default().into_http_connector()),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -21,9 +19,9 @@ pub async fn serve_http_request(
|
|||||||
proxy_addr: &str,
|
proxy_addr: &str,
|
||||||
headers: &http::header::HeaderMap,
|
headers: &http::header::HeaderMap,
|
||||||
client_ip: net::IpAddr,
|
client_ip: net::IpAddr,
|
||||||
mut req: hyper::Request<Incoming>,
|
mut req: hyper::Request<hyper::Body>,
|
||||||
req_is_https: bool,
|
req_is_https: bool,
|
||||||
) -> unexpected::Result<hyper::Response<Incoming>> {
|
) -> unexpected::Result<hyper::Response<hyper::Body>> {
|
||||||
for (name, value) in headers {
|
for (name, value) in headers {
|
||||||
if value.is_empty() {
|
if value.is_empty() {
|
||||||
req.headers_mut().remove(name);
|
req.headers_mut().remove(name);
|
||||||
|
@ -1,121 +1,68 @@
|
|||||||
use crate::error::unexpected::{self, Intoable, Mappable};
|
use crate::error::unexpected::{self, Mappable};
|
||||||
use crate::service;
|
use crate::service;
|
||||||
|
|
||||||
use std::{net, pin, sync};
|
use std::{convert, future, sync};
|
||||||
|
|
||||||
|
use futures::StreamExt;
|
||||||
|
use hyper::server::conn::AddrStream;
|
||||||
|
use tokio_rustls::server::TlsStream;
|
||||||
use tokio_util::sync::CancellationToken;
|
use tokio_util::sync::CancellationToken;
|
||||||
|
|
||||||
async fn serve_conn<Conn>(
|
|
||||||
service: sync::Arc<service::http::Service>,
|
|
||||||
canceller: CancellationToken,
|
|
||||||
conn: Conn,
|
|
||||||
remote_addr: net::SocketAddr,
|
|
||||||
req_is_https: bool,
|
|
||||||
) where
|
|
||||||
Conn: tokio::io::AsyncRead + tokio::io::AsyncWrite + Unpin + 'static,
|
|
||||||
{
|
|
||||||
log::debug!("[{remote_addr}] Handling incoming connection (is_https:{req_is_https})");
|
|
||||||
let service = crate::service::http::HyperServiceImpl::new(
|
|
||||||
service.clone(),
|
|
||||||
remote_addr.ip(),
|
|
||||||
req_is_https,
|
|
||||||
);
|
|
||||||
|
|
||||||
use core::time::Duration;
|
|
||||||
use hyper_util::{
|
|
||||||
rt::tokio::{TokioExecutor, TokioIo, TokioTimer},
|
|
||||||
server::conn::auto::Builder,
|
|
||||||
};
|
|
||||||
|
|
||||||
let timer = TokioTimer::new();
|
|
||||||
|
|
||||||
let mut builder = Builder::new(TokioExecutor::new());
|
|
||||||
builder
|
|
||||||
.http1()
|
|
||||||
.timer(timer.clone())
|
|
||||||
.header_read_timeout(Duration::from_secs(5))
|
|
||||||
.http2()
|
|
||||||
.timer(timer)
|
|
||||||
.keep_alive_interval(Some(Duration::from_secs(10)))
|
|
||||||
.keep_alive_timeout(Duration::from_secs(5));
|
|
||||||
|
|
||||||
let mut conn = pin::pin!(builder.serve_connection(TokioIo::new(conn), service));
|
|
||||||
|
|
||||||
tokio::select! {
|
|
||||||
res = conn.as_mut() => {
|
|
||||||
if let Err(err) = res {
|
|
||||||
log::error!("[{remote_addr}] Failed to serve HTTP(S) request: {err}")
|
|
||||||
} else {
|
|
||||||
log::debug!("[{remote_addr}] Finished handling connection");
|
|
||||||
}
|
|
||||||
return
|
|
||||||
},
|
|
||||||
_ = canceller.cancelled() => (),
|
|
||||||
}
|
|
||||||
|
|
||||||
log::debug!("[{remote_addr}] received cancellation notice, gracefully shutting down...");
|
|
||||||
conn.as_mut().graceful_shutdown();
|
|
||||||
|
|
||||||
let timeout_res = tokio::time::timeout(Duration::from_secs(5), async {
|
|
||||||
if let Err(err) = conn.await {
|
|
||||||
log::error!("[{remote_addr}] Failed to serve HTTP(S) request after shutdown: {err}")
|
|
||||||
} else {
|
|
||||||
log::debug!("[{remote_addr}] Finished handling connection after shutdown");
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
|
|
||||||
if timeout_res.is_err() {
|
|
||||||
log::debug!("[{remote_addr}] did not gracefully shutdown, forcing shutdown")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn listen_http(
|
pub async fn listen_http(
|
||||||
service: sync::Arc<service::http::Service>,
|
service: sync::Arc<service::http::Service>,
|
||||||
canceller: CancellationToken,
|
canceller: CancellationToken,
|
||||||
) -> unexpected::Result<()> {
|
) -> Result<(), unexpected::Error> {
|
||||||
let mut wg = awaitgroup::WaitGroup::new();
|
|
||||||
let addr = service.config.http.http_addr;
|
let addr = service.config.http.http_addr;
|
||||||
let listener = tokio::net::TcpListener::bind(addr)
|
|
||||||
.await
|
let make_service = hyper::service::make_service_fn(move |conn: &AddrStream| {
|
||||||
.map_unexpected_while(|| format!("creating TCP listener on {addr}"))?;
|
let service = service.clone();
|
||||||
|
let client_ip = conn.remote_addr().ip();
|
||||||
|
|
||||||
|
// Create a `Service` for responding to the request.
|
||||||
|
let hyper_service = hyper::service::service_fn(move |req| {
|
||||||
|
let service = service.clone();
|
||||||
|
async move {
|
||||||
|
Ok::<_, convert::Infallible>(service.handle_request(client_ip, req, false).await)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Return the service to hyper.
|
||||||
|
async move { Ok::<_, convert::Infallible>(hyper_service) }
|
||||||
|
});
|
||||||
|
|
||||||
log::info!("Listening on http://{}", &addr);
|
log::info!("Listening on http://{}", &addr);
|
||||||
|
let server = hyper::Server::bind(&addr).serve(make_service);
|
||||||
|
|
||||||
loop {
|
let graceful = server.with_graceful_shutdown(async {
|
||||||
tokio::select! {
|
canceller.cancelled().await;
|
||||||
accept_res = listener.accept() => {
|
|
||||||
match accept_res {
|
|
||||||
Ok((stream, remote_addr)) => {
|
|
||||||
let worker = wg.worker();
|
|
||||||
let service = service.clone();
|
|
||||||
let canceller = canceller.clone();
|
|
||||||
tokio::task::spawn(async move {
|
|
||||||
serve_conn(service, canceller, stream, remote_addr, false).await;
|
|
||||||
worker.done()
|
|
||||||
});
|
});
|
||||||
},
|
|
||||||
Err(err) =>
|
graceful.await.or_unexpected()
|
||||||
return Err(err.into_unexpected_while(format!("accepting new HTTP requests on {addr}"))),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ = canceller.cancelled() => {
|
|
||||||
log::info!("No longer accepting new requests on http://{addr}, waiting on remaining requests...");
|
|
||||||
wg.wait().await;
|
|
||||||
log::info!("All requests on http://{addr} have completed");
|
|
||||||
return Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn listen_https(
|
pub async fn listen_https(
|
||||||
service: sync::Arc<service::http::Service>,
|
service: sync::Arc<service::http::Service>,
|
||||||
canceller: CancellationToken,
|
canceller: CancellationToken,
|
||||||
) -> Result<(), unexpected::Error> {
|
) -> Result<(), unexpected::Error> {
|
||||||
let mut wg = awaitgroup::WaitGroup::new();
|
|
||||||
let cert_resolver = service.cert_resolver.clone();
|
let cert_resolver = service.cert_resolver.clone();
|
||||||
let addr = service.config.http.https_addr.unwrap();
|
let addr = service.config.http.https_addr.unwrap();
|
||||||
|
|
||||||
|
let make_service = hyper::service::make_service_fn(move |conn: &TlsStream<AddrStream>| {
|
||||||
|
let service = service.clone();
|
||||||
|
let client_ip = conn.get_ref().0.remote_addr().ip();
|
||||||
|
|
||||||
|
// Create a `Service` for responding to the request.
|
||||||
|
let hyper_service = hyper::service::service_fn(move |req| {
|
||||||
|
let service = service.clone();
|
||||||
|
async move {
|
||||||
|
Ok::<_, convert::Infallible>(service.handle_request(client_ip, req, true).await)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Return the service to hyper.
|
||||||
|
async move { Ok::<_, convert::Infallible>(hyper_service) }
|
||||||
|
});
|
||||||
|
|
||||||
let server_config: tokio_rustls::TlsAcceptor = sync::Arc::new(
|
let server_config: tokio_rustls::TlsAcceptor = sync::Arc::new(
|
||||||
rustls::server::ServerConfig::builder()
|
rustls::server::ServerConfig::builder()
|
||||||
.with_safe_defaults()
|
.with_safe_defaults()
|
||||||
@ -124,46 +71,27 @@ pub async fn listen_https(
|
|||||||
)
|
)
|
||||||
.into();
|
.into();
|
||||||
|
|
||||||
let listener = tokio::net::TcpListener::bind(addr)
|
let addr_incoming = hyper::server::conn::AddrIncoming::bind(&addr)
|
||||||
.await
|
.expect("https listen socket creation failed");
|
||||||
.map_unexpected_while(|| format!("creating TCP listener on {addr}"))?;
|
|
||||||
|
|
||||||
log::info!("Listening on https://{}", &addr);
|
let incoming = tls_listener::TlsListener::new(server_config, addr_incoming).filter(|conn| {
|
||||||
|
if let Err(err) = conn {
|
||||||
loop {
|
log::error!("Error accepting TLS connection: {:?}", err);
|
||||||
tokio::select! {
|
future::ready(false)
|
||||||
accept_res = listener.accept() => {
|
} else {
|
||||||
match accept_res {
|
future::ready(true)
|
||||||
Ok((raw_stream, remote_addr)) => {
|
|
||||||
let worker = wg.worker();
|
|
||||||
let server_config = server_config.clone();
|
|
||||||
let service = service.clone();
|
|
||||||
let canceller = canceller.clone();
|
|
||||||
|
|
||||||
tokio::task::spawn(async move {
|
|
||||||
let stream = match server_config.accept(raw_stream).await {
|
|
||||||
Ok(s) => s,
|
|
||||||
Err(err) => {
|
|
||||||
log::warn!("failed to accept TLS connection on {addr}: {err}");
|
|
||||||
worker.done();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
serve_conn(service, canceller, stream, remote_addr, true).await;
|
|
||||||
worker.done();
|
|
||||||
});
|
});
|
||||||
},
|
|
||||||
Err(err) =>
|
let incoming = hyper::server::accept::from_stream(incoming);
|
||||||
return Err(err.into_unexpected_while(format!("accepting new HTTPS requests on {addr}"))),
|
|
||||||
}
|
log::info!("Listening on https://{}", addr);
|
||||||
},
|
|
||||||
_ = canceller.cancelled() => {
|
let server = hyper::Server::builder(incoming).serve(make_service);
|
||||||
log::info!("No longer accepting new requests on https://{addr}, waiting on remaining requests...");
|
|
||||||
wg.wait().await;
|
let graceful = server.with_graceful_shutdown(async {
|
||||||
log::info!("All requests on https://{addr} have completed");
|
canceller.cancelled().await;
|
||||||
return Ok(())
|
});
|
||||||
}
|
|
||||||
}
|
graceful.await.or_unexpected()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
11
src/util.rs
11
src/util.rs
@ -68,14 +68,3 @@ impl BoxByteStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub type BoxFuture<'a, O> = pin::Pin<Box<dyn futures::Future<Output = O> + Send + 'a>>;
|
pub type BoxFuture<'a, O> = pin::Pin<Box<dyn futures::Future<Output = O> + Send + 'a>>;
|
||||||
|
|
||||||
pub fn try_collect<I, V, E>(iter: I) -> Result<Vec<V>, E>
|
|
||||||
where
|
|
||||||
I: std::iter::Iterator<Item = Result<V, E>>,
|
|
||||||
{
|
|
||||||
let mut res = Vec::<V>::new();
|
|
||||||
for v in iter {
|
|
||||||
res.push(v?);
|
|
||||||
}
|
|
||||||
Ok(res)
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user