use std::time::Duration;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AuthConfig {
pub secret: String,
pub public_paths: Vec<String>,
}
impl AuthConfig {
pub fn is_public(&self, path: &str) -> bool {
self.public_paths.iter().any(|item| item == path)
}
}
#[derive(Debug, Clone)]
pub struct RestConfig {
pub name: String,
pub timeout: Duration,
pub max_body_bytes: usize,
pub auth: Option<AuthConfig>,
pub middlewares: RestMiddlewareConfig,
#[cfg(feature = "observability")]
pub metrics_registry: Option<crate::observability::MetricsRegistry>,
}
impl Default for RestConfig {
fn default() -> Self {
Self {
name: "rs-zero".to_string(),
timeout: Duration::from_secs(5),
max_body_bytes: 1024 * 1024,
auth: None,
middlewares: RestMiddlewareConfig::default(),
#[cfg(feature = "observability")]
metrics_registry: None,
}
}
}
impl RestConfig {
pub fn production_defaults(name: impl Into<String>) -> Self {
Self {
name: name.into(),
middlewares: RestMiddlewareConfig {
resilience: RestResilienceConfig::production_defaults(),
metrics: RestMetricsConfig { enabled: true },
},
..Self::default()
}
}
#[cfg(all(feature = "resil", feature = "cache-redis"))]
pub fn production_defaults_with_redis_limiter(
name: impl Into<String>,
limiter: RestRateLimiterConfig,
) -> Self {
let mut config = Self::production_defaults(name);
config.middlewares.resilience.rate_limiter = limiter;
config
}
#[allow(deprecated)]
#[deprecated(note = "use production_defaults instead")]
pub fn go_zero_defaults(name: impl Into<String>) -> Self {
Self::production_defaults(name)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct RestMiddlewareConfig {
pub resilience: RestResilienceConfig,
pub metrics: RestMetricsConfig,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RestResilienceConfig {
pub breaker_enabled: bool,
pub breaker_failure_threshold: u32,
pub breaker_reset_timeout: Duration,
pub breaker_sre_enabled: bool,
pub breaker_sre_k_millis: u32,
pub breaker_sre_protection: u64,
pub max_concurrency: Option<usize>,
pub request_timeout: Option<Duration>,
pub shedding_enabled: bool,
pub shedding_max_in_flight: Option<usize>,
pub shedding_min_request_count: u64,
pub shedding_max_latency: Duration,
pub shedding_cpu_threshold_millis: u32,
pub shedding_cool_off: Duration,
pub shedding_window_buckets: usize,
pub shedding_window_bucket_duration: Duration,
#[cfg(all(feature = "resil", feature = "cache-redis"))]
pub rate_limiter: RestRateLimiterConfig,
}
impl Default for RestResilienceConfig {
fn default() -> Self {
Self {
breaker_enabled: false,
breaker_failure_threshold: 5,
breaker_reset_timeout: Duration::from_secs(30),
breaker_sre_enabled: false,
breaker_sre_k_millis: 1500,
breaker_sre_protection: 5,
max_concurrency: None,
request_timeout: None,
shedding_enabled: false,
shedding_max_in_flight: None,
shedding_min_request_count: 20,
shedding_max_latency: Duration::from_millis(250),
shedding_cpu_threshold_millis: 900,
shedding_cool_off: Duration::from_secs(1),
shedding_window_buckets: 50,
shedding_window_bucket_duration: Duration::from_millis(100),
#[cfg(all(feature = "resil", feature = "cache-redis"))]
rate_limiter: RestRateLimiterConfig::default(),
}
}
}
impl RestResilienceConfig {
pub fn production_defaults() -> Self {
Self {
breaker_enabled: true,
breaker_sre_enabled: true,
max_concurrency: Some(1024),
request_timeout: Some(Duration::from_secs(5)),
shedding_enabled: true,
shedding_max_in_flight: Some(1024),
shedding_min_request_count: 20,
shedding_max_latency: Duration::from_millis(250),
..Self::default()
}
}
#[allow(deprecated)]
#[deprecated(note = "use production_defaults instead")]
pub fn go_zero_defaults() -> Self {
Self::production_defaults()
}
}
#[cfg(all(feature = "resil", feature = "cache-redis"))]
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub enum RestRateLimiterConfig {
#[default]
Disabled,
RedisToken(crate::resil::RedisTokenLimiterConfig),
RedisPeriod(crate::resil::RedisPeriodLimiterConfig),
}
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct RestMetricsConfig {
pub enabled: bool,
}