mod layer;
mod service;
pub use layer::ProxyLayer;
pub use service::{ProxyRequest, ProxyResponse, ProxyTowerService};
use serde_json::Value;
use std::collections::HashMap;
use std::time::Duration;
#[derive(Debug, Clone)]
pub struct ProxyLayerConfig {
pub timeout: Duration,
pub include_timing: bool,
pub bypass_methods: Vec<String>,
pub default_metadata: HashMap<String, Value>,
pub enable_logging: bool,
}
impl Default for ProxyLayerConfig {
fn default() -> Self {
Self {
timeout: Duration::from_secs(30),
include_timing: true,
bypass_methods: Vec::new(),
default_metadata: HashMap::new(),
enable_logging: true,
}
}
}
impl ProxyLayerConfig {
#[must_use]
pub fn with_timeout(timeout: Duration) -> Self {
Self {
timeout,
..Default::default()
}
}
#[must_use]
pub fn timeout(mut self, timeout: Duration) -> Self {
self.timeout = timeout;
self
}
#[must_use]
pub fn bypass_method(mut self, method: impl Into<String>) -> Self {
self.bypass_methods.push(method.into());
self
}
#[must_use]
pub fn with_metadata(mut self, key: impl Into<String>, value: Value) -> Self {
self.default_metadata.insert(key.into(), value);
self
}
#[must_use]
pub fn include_timing(mut self, include: bool) -> Self {
self.include_timing = include;
self
}
#[must_use]
pub fn enable_logging(mut self, enable: bool) -> Self {
self.enable_logging = enable;
self
}
#[must_use]
pub fn should_bypass(&self, method: &str) -> bool {
self.bypass_methods.iter().any(|m| m == method)
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn test_default_config() {
let config = ProxyLayerConfig::default();
assert_eq!(config.timeout, Duration::from_secs(30));
assert!(config.include_timing);
assert!(config.bypass_methods.is_empty());
assert!(config.default_metadata.is_empty());
assert!(config.enable_logging);
}
#[test]
fn test_with_timeout() {
let config = ProxyLayerConfig::with_timeout(Duration::from_secs(60));
assert_eq!(config.timeout, Duration::from_secs(60));
}
#[test]
fn test_bypass_methods() {
let config = ProxyLayerConfig::default()
.bypass_method("ping")
.bypass_method("health");
assert!(config.should_bypass("ping"));
assert!(config.should_bypass("health"));
assert!(!config.should_bypass("tools/call"));
}
#[test]
fn test_with_metadata() {
let config = ProxyLayerConfig::default()
.with_metadata("version", json!("1.0.0"))
.with_metadata("proxy_id", json!("proxy-1"));
assert_eq!(
config.default_metadata.get("version"),
Some(&json!("1.0.0"))
);
assert_eq!(
config.default_metadata.get("proxy_id"),
Some(&json!("proxy-1"))
);
}
#[test]
fn test_config_builder() {
let config = ProxyLayerConfig::default()
.timeout(Duration::from_secs(120))
.include_timing(false)
.enable_logging(false);
assert_eq!(config.timeout, Duration::from_secs(120));
assert!(!config.include_timing);
assert!(!config.enable_logging);
}
}