use std::sync::Arc;
use tower::Layer;
use crate::proxy::ProxyService;
use super::ProxyLayerConfig;
use super::service::ProxyTowerService;
#[derive(Clone)]
pub struct ProxyLayer {
proxy: Arc<ProxyService>,
config: ProxyLayerConfig,
}
impl std::fmt::Debug for ProxyLayer {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ProxyLayer")
.field("config", &self.config)
.finish_non_exhaustive()
}
}
impl ProxyLayer {
#[must_use]
pub fn new(proxy: ProxyService) -> Self {
Self {
proxy: Arc::new(proxy),
config: ProxyLayerConfig::default(),
}
}
#[must_use]
pub fn from_arc(proxy: Arc<ProxyService>) -> Self {
Self {
proxy,
config: ProxyLayerConfig::default(),
}
}
#[must_use]
pub fn with_config(proxy: ProxyService, config: ProxyLayerConfig) -> Self {
Self {
proxy: Arc::new(proxy),
config,
}
}
#[must_use]
pub fn config(mut self, config: ProxyLayerConfig) -> Self {
self.config = config;
self
}
#[must_use]
pub fn bypass_method(mut self, method: impl Into<String>) -> Self {
self.config.bypass_methods.push(method.into());
self
}
#[must_use]
pub fn timeout(mut self, timeout: std::time::Duration) -> Self {
self.config.timeout = timeout;
self
}
#[must_use]
pub fn include_timing(mut self, include: bool) -> Self {
self.config.include_timing = include;
self
}
#[must_use]
pub fn enable_logging(mut self, enable: bool) -> Self {
self.config.enable_logging = enable;
self
}
}
impl<S> Layer<S> for ProxyLayer {
type Service = ProxyTowerService;
fn layer(&self, _inner: S) -> Self::Service {
ProxyTowerService::from_arc(Arc::clone(&self.proxy), self.config.clone())
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::time::Duration;
#[test]
fn test_layer_creation() {
let config = ProxyLayerConfig::default();
assert_eq!(config.timeout, Duration::from_secs(30));
}
#[test]
fn test_config_builder() {
let config = ProxyLayerConfig::default()
.timeout(Duration::from_secs(60))
.bypass_method("ping")
.include_timing(false)
.enable_logging(false);
assert_eq!(config.timeout, Duration::from_secs(60));
assert!(config.should_bypass("ping"));
assert!(!config.include_timing);
assert!(!config.enable_logging);
}
#[test]
fn test_layer_config_methods() {
let mut config = ProxyLayerConfig::default();
config.bypass_methods.push("test".to_string());
assert!(config.should_bypass("test"));
assert!(!config.should_bypass("other"));
}
}