tower_http_cache/admin/
mod.rs1pub mod routes;
8pub mod stats;
9
10use crate::backend::CacheBackend;
11use std::sync::Arc;
12
13#[derive(Debug, Clone)]
15pub struct AdminConfig {
16 pub enabled: bool,
18
19 pub auth_token: Option<String>,
21
22 pub require_auth: bool,
24
25 pub mount_path: String,
27
28 pub max_keys_per_request: usize,
30
31 pub max_hot_keys: usize,
33}
34
35impl Default for AdminConfig {
36 fn default() -> Self {
37 Self {
38 enabled: false,
39 auth_token: None,
40 require_auth: true,
41 mount_path: "/admin/cache".to_string(),
42 max_keys_per_request: 100,
43 max_hot_keys: 20,
44 }
45 }
46}
47
48impl AdminConfig {
49 pub fn new() -> Self {
51 Self::default()
52 }
53
54 pub fn with_enabled(mut self, enabled: bool) -> Self {
56 self.enabled = enabled;
57 self
58 }
59
60 pub fn with_auth_token(mut self, token: impl Into<String>) -> Self {
62 self.auth_token = Some(token.into());
63 self
64 }
65
66 pub fn with_require_auth(mut self, require: bool) -> Self {
68 self.require_auth = require;
69 self
70 }
71
72 pub fn with_mount_path(mut self, path: impl Into<String>) -> Self {
74 self.mount_path = path.into();
75 self
76 }
77
78 pub fn validate_token(&self, provided: Option<&str>) -> bool {
80 if !self.require_auth {
81 return true;
82 }
83
84 match (&self.auth_token, provided) {
85 (Some(expected), Some(provided)) => expected == provided,
86 (None, _) => !self.require_auth,
87 _ => false,
88 }
89 }
90}
91
92#[derive(Clone)]
94pub struct AdminState<B: CacheBackend> {
95 pub backend: B,
96 pub config: Arc<AdminConfig>,
97 pub stats: Arc<stats::GlobalStats>,
98}
99
100impl<B: CacheBackend> AdminState<B> {
101 pub fn new(backend: B, config: AdminConfig) -> Self {
103 Self {
104 backend,
105 config: Arc::new(config),
106 stats: Arc::new(stats::GlobalStats::new()),
107 }
108 }
109}
110
111#[cfg(test)]
112mod tests {
113 use super::*;
114
115 #[test]
116 fn admin_config_default() {
117 let config = AdminConfig::default();
118 assert!(!config.enabled);
119 assert!(config.require_auth);
120 assert_eq!(config.mount_path, "/admin/cache");
121 }
122
123 #[test]
124 fn admin_config_builder() {
125 let config = AdminConfig::new()
126 .with_enabled(true)
127 .with_auth_token("secret")
128 .with_require_auth(false)
129 .with_mount_path("/cache/admin");
130
131 assert!(config.enabled);
132 assert_eq!(config.auth_token, Some("secret".to_string()));
133 assert!(!config.require_auth);
134 assert_eq!(config.mount_path, "/cache/admin");
135 }
136
137 #[test]
138 fn validate_token_success() {
139 let config = AdminConfig::new()
140 .with_auth_token("secret")
141 .with_require_auth(true);
142
143 assert!(config.validate_token(Some("secret")));
144 }
145
146 #[test]
147 fn validate_token_failure() {
148 let config = AdminConfig::new()
149 .with_auth_token("secret")
150 .with_require_auth(true);
151
152 assert!(!config.validate_token(Some("wrong")));
153 assert!(!config.validate_token(None));
154 }
155
156 #[test]
157 fn validate_token_no_auth_required() {
158 let config = AdminConfig::new().with_require_auth(false);
159
160 assert!(config.validate_token(None));
161 assert!(config.validate_token(Some("anything")));
162 }
163}