From 3b1afad1d1a697e82c003e146ef2b7d5742e5210 Mon Sep 17 00:00:00 2001 From: metamuffin Date: Tue, 14 Nov 2023 11:54:01 +0100 Subject: refactor architecture and start on http basic auth --- src/config.rs | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 76 insertions(+), 6 deletions(-) (limited to 'src/config.rs') 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, + pub hosts: HashMap, } #[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); + +#[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, } #[derive(Debug, Serialize, Deserialize)] @@ -50,6 +75,51 @@ pub struct FileserverConfig { pub index: bool, } +// try deser Vec but fall back to deser T and putting that in Vec +fn seq_or_not<'de, D, V: Deserialize<'de>>(des: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + struct SeqOrNot(PhantomData); + impl<'de, V: Deserialize<'de>> Visitor<'de> for SeqOrNot { + type Value = Vec; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a sequence or not a sequence") + } + fn visit_enum(self, data: A) -> Result + where + A: serde::de::EnumAccess<'de>, + { + Ok(vec![V::deserialize(value::EnumAccessDeserializer::new( + data, + ))?]) + } + fn visit_map(self, map: A) -> Result + where + A: serde::de::MapAccess<'de>, + { + Ok(vec![V::deserialize(value::MapAccessDeserializer::new( + map, + ))?]) + } + fn visit_str(self, val: &str) -> Result, E> + where + E: Error, + { + Ok(vec![V::deserialize(value::StrDeserializer::new(val))?]) + } + + fn visit_seq(self, val: A) -> Result, A::Error> + where + A: SeqAccess<'de>, + { + Vec::::deserialize(value::SeqAccessDeserializer::new(val)) + } + } + des.deserialize_any(SeqOrNot::(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, D::Error> where -- cgit v1.2.3-70-g09d2