diff --git a/config-example.toml b/config-example.toml index 9b2b463..673f4db 100644 --- a/config-example.toml +++ b/config-example.toml @@ -60,8 +60,8 @@ path = '/maps' # For request path starting with "/maps", # this configuration results that any path like "/maps/org/any.ext" is mapped to "/replacing/path1/org/any.ext" # by replacing "/maps" with "/replacing/path1" for routing to the locations given in upstream array -# Note that unless "path_replaced_with" is specified, the "path" is always preserved. -# "path_replaced_with" must be start from "/" (root path) +# Note that unless "replace_path" is specified, the "path" is always preserved. +# "replace_path" must be start from "/" (root path) replace_path = "/replacing/path1" upstream = [ { location = 'www.bing.com', tls = true }, diff --git a/src/backend/mod.rs b/src/backend/mod.rs index 409222d..a31fd15 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -28,12 +28,15 @@ use x509_parser::prelude::*; #[derive(Builder)] pub struct Backend { #[builder(setter(into))] + /// backend application name, e.g., app1 pub app_name: String, #[builder(setter(custom))] + /// server name, e.g., example.com, in String ascii lower case pub server_name: String, + /// struct of reverse proxy serving incoming request pub reverse_proxy: ReverseProxy, - // tls settings + /// tls settings #[builder(setter(custom), default)] pub tls_cert_path: Option, #[builder(setter(custom), default)] diff --git a/src/backend/upstream.rs b/src/backend/upstream.rs index c2fdb34..2a56cae 100644 --- a/src/backend/upstream.rs +++ b/src/backend/upstream.rs @@ -17,6 +17,7 @@ pub struct ReverseProxy { } impl ReverseProxy { + /// Get an appropriate upstream destination for given path string. pub fn get<'a>(&self, path_str: impl Into>) -> Option<&UpstreamGroup> { // trie使ってlongest prefix match させてもいいけどルート記述は少ないと思われるので、 // コスト的にこの程度で十分 @@ -52,9 +53,14 @@ impl ReverseProxy { #[allow(dead_code)] #[derive(Debug, Clone)] +/// Load Balancing Option pub enum LoadBalance { + /// Simple round robin without session persistance RoundRobin, + /// Randomly chose one upstream server Random, + /// Round robin with session persistance using cookie + StickyRoundRobin, } impl Default for LoadBalance { fn default() -> Self { @@ -63,22 +69,32 @@ impl Default for LoadBalance { } #[derive(Debug, Clone)] +/// Upstream struct just containing uri without path pub struct Upstream { - pub uri: hyper::Uri, // base uri without specific path + /// Base uri without specific path + pub uri: hyper::Uri, } #[derive(Debug, Clone, Builder)] +/// Struct serving multiple upstream servers for, e.g., load balancing. pub struct UpstreamGroup { + /// Upstream server(s) pub upstream: Vec, #[builder(setter(custom), default)] + /// Path like "/path" in [[PathNameBytesExp]] associated with the upstream server(s) pub path: PathNameBytesExp, #[builder(setter(custom), default)] + /// Path in [[PathNameBytesExp]] that will be used to replace the "path" part of incoming url pub replace_path: Option, + #[builder(default)] + /// Load balancing option pub lb: LoadBalance, #[builder(default)] - pub cnt: UpstreamCount, // counter for load balancing + /// Counter for load balancing + pub cnt: UpstreamCount, #[builder(setter(custom), default)] + /// Activated upstream options defined in [[UpstreamOption]] pub opts: HashSet, } impl UpstreamGroupBuilder { @@ -116,6 +132,7 @@ impl UpstreamGroupBuilder { pub struct UpstreamCount(Arc); impl UpstreamGroup { + /// Get an enabled option of load balancing [[LoadBalance]] pub fn get(&self) -> Option<&Upstream> { match self.lb { LoadBalance::RoundRobin => { @@ -127,13 +144,16 @@ impl UpstreamGroup { let max = self.upstream.len() - 1; self.upstream.get(rng.gen_range(0..max)) } + LoadBalance::StickyRoundRobin => todo!(), // TODO: TODO: } } + /// Get a current count of upstream served fn current_cnt(&self) -> usize { self.cnt.0.load(Ordering::Relaxed) } + /// Increment count of upstream served fn increment_cnt(&self) -> usize { if self.current_cnt() < self.upstream.len() - 1 { self.cnt.0.fetch_add(1, Ordering::Relaxed) diff --git a/src/handler/handler_main.rs b/src/handler/handler_main.rs index 2ef5665..664f5e4 100644 --- a/src/handler/handler_main.rs +++ b/src/handler/handler_main.rs @@ -266,6 +266,8 @@ where }; // Fix unique upstream destination since there could be multiple ones. + // TODO: StickyならCookieをここでgetに与える必要 + // TODO: Stickyで、Cookieが与えられなかったらset-cookie向けにcookieを返す必要。upstreamオブジェクトに含めるのも手。 let upstream_chosen = upstream_group.get().ok_or_else(|| anyhow!("Failed to get upstream"))?; // apply upstream-specific headers given in upstream_option diff --git a/src/utils/bytes_name.rs b/src/utils/bytes_name.rs index 80bc0f0..16ec7ab 100644 --- a/src/utils/bytes_name.rs +++ b/src/utils/bytes_name.rs @@ -1,5 +1,5 @@ /// Server name (hostname or ip address) representation in bytes-based struct -/// For searching hashmap or key list by exact or longest-prefix matching +/// for searching hashmap or key list by exact or longest-prefix matching #[derive(Clone, Debug, PartialEq, Eq, Hash, Default)] pub struct ServerNameBytesExp(pub Vec); // lowercase ascii bytes impl From<&[u8]> for ServerNameBytesExp { @@ -8,8 +8,8 @@ impl From<&[u8]> for ServerNameBytesExp { } } -/// Server name (hostname or ip address) representation in bytes-based struct -/// For searching hashmap or key list by exact or longest-prefix matching +/// Path name, like "/path/ok", represented in bytes-based struct +/// for searching hashmap or key list by exact or longest-prefix matching #[derive(Clone, Debug, PartialEq, Eq, Hash, Default)] pub struct PathNameBytesExp(pub Vec); // lowercase ascii bytes impl PathNameBytesExp {