aboutsummaryrefslogtreecommitdiff
path: root/src/config.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/config.rs')
-rw-r--r--src/config.rs82
1 files changed, 76 insertions, 6 deletions
diff --git a/src/config.rs b/src/config.rs
index c686930..a7abf3b 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -3,7 +3,14 @@ use serde::{
de::{value, Error, SeqAccess, Visitor},
Deserialize, Deserializer, Serialize,
};
-use std::{collections::HashMap, fmt, fs::read_to_string, net::SocketAddr, path::PathBuf};
+use std::{
+ collections::{HashMap, HashSet},
+ fmt,
+ fs::read_to_string,
+ marker::PhantomData,
+ net::SocketAddr,
+ path::PathBuf,
+};
#[derive(Debug, Serialize, Deserialize)]
pub struct Config {
@@ -12,7 +19,7 @@ pub struct Config {
#[serde(default)]
pub limits: Limits,
#[serde(default)]
- pub hosts: HashMap<String, HostConfig>,
+ pub hosts: HashMap<String, Route>,
}
#[derive(Debug, Serialize, Deserialize)]
@@ -37,10 +44,28 @@ pub struct HttpsConfig {
}
#[derive(Debug, Serialize, Deserialize)]
-#[serde(untagged)]
-pub enum HostConfig {
- Backend { backend: SocketAddr },
- Files { files: FileserverConfig },
+pub struct Route(#[serde(deserialize_with = "seq_or_not")] pub Vec<RouteFilter>);
+
+#[derive(Debug, Serialize, Deserialize)]
+#[serde(rename_all = "snake_case")]
+pub enum RouteFilter {
+ HttpBasicAuth {
+ #[serde(flatten)]
+ config: HttpBasicAuthConfig,
+ },
+ Proxy {
+ backend: SocketAddr,
+ },
+ Files {
+ #[serde(flatten)]
+ config: FileserverConfig,
+ },
+}
+
+#[derive(Debug, Serialize, Deserialize)]
+pub struct HttpBasicAuthConfig {
+ pub realm: String,
+ pub valid: HashSet<String>,
}
#[derive(Debug, Serialize, Deserialize)]
@@ -50,6 +75,51 @@ pub struct FileserverConfig {
pub index: bool,
}
+// try deser Vec<T> but fall back to deser T and putting that in Vec
+fn seq_or_not<'de, D, V: Deserialize<'de>>(des: D) -> Result<Vec<V>, D::Error>
+where
+ D: Deserializer<'de>,
+{
+ struct SeqOrNot<V>(PhantomData<V>);
+ impl<'de, V: Deserialize<'de>> Visitor<'de> for SeqOrNot<V> {
+ type Value = Vec<V>;
+
+ fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("a sequence or not a sequence")
+ }
+ fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
+ where
+ A: serde::de::EnumAccess<'de>,
+ {
+ Ok(vec![V::deserialize(value::EnumAccessDeserializer::new(
+ data,
+ ))?])
+ }
+ fn visit_map<A>(self, map: A) -> Result<Self::Value, A::Error>
+ where
+ A: serde::de::MapAccess<'de>,
+ {
+ Ok(vec![V::deserialize(value::MapAccessDeserializer::new(
+ map,
+ ))?])
+ }
+ fn visit_str<E>(self, val: &str) -> Result<Vec<V>, E>
+ where
+ E: Error,
+ {
+ Ok(vec![V::deserialize(value::StrDeserializer::new(val))?])
+ }
+
+ fn visit_seq<A>(self, val: A) -> Result<Vec<V>, A::Error>
+ where
+ A: SeqAccess<'de>,
+ {
+ Vec::<V>::deserialize(value::SeqAccessDeserializer::new(val))
+ }
+ }
+ des.deserialize_any(SeqOrNot::<V>(PhantomData))
+}
+
// fall back to expecting a single string and putting that in a 1-length vector
fn string_or_seq<'de, D>(des: D) -> Result<Vec<SocketAddr>, D::Error>
where