Skip to main content
Glama
lib.rs3.43 kB
use std::{ net::SocketAddr, sync::Arc, }; use serde::Serialize; use serde_json::Value; use thiserror::Error; pub mod axum_integration; pub mod server; /// Sensitive field name patterns that should be redacted in config output. /// Add any substring that appears in field names containing sensitive data. const SENSITIVE_FIELD_PATTERNS: &[&str] = &[ "auth", "credential", "creds", "key", "password", "secret", "token", ]; #[derive(Debug, Error)] pub enum ServiceEndpointsError { #[error("HTTP server error: {0}")] HttpServer(#[from] std::io::Error), #[error("JSON serialization error: {0}")] JsonSerialization(#[from] serde_json::Error), } pub type Result<T> = std::result::Result<T, ServiceEndpointsError>; /// Service endpoints implementation for health and config pub struct DefaultServiceEndpoints { service_name: String, config: Arc<Value>, } impl DefaultServiceEndpoints { /// Create a new DefaultServiceEndpoints with a JSON config value pub fn new(service_name: impl Into<String>, config: Value) -> Self { Self { service_name: service_name.into(), config: Arc::new(config), } } /// Create from any serializable config object, redacting sensitive fields for safe exposure pub fn from_config<T: Serialize>(service_name: impl Into<String>, config: &T) -> Result<Self> { let mut value = serde_json::to_value(config)?; redact_sensitive_fields(&mut value); Ok(Self::new(service_name, value)) } pub fn service_name(&self) -> &str { &self.service_name } pub fn config(&self) -> &Value { &self.config } } #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct ServiceEndpointsConfig { pub enabled: bool, pub bind_address: SocketAddr, pub health_endpoint: String, pub config_endpoint: String, } impl Default for ServiceEndpointsConfig { fn default() -> Self { Self { enabled: false, bind_address: "127.0.0.1:8080".parse().unwrap(), health_endpoint: "/health".to_string(), config_endpoint: "/config".to_string(), } } } impl ServiceEndpointsConfig { /// Create a new config with endpoints enabled on the given port pub fn new(port: u16) -> Self { Self { enabled: true, bind_address: format!("127.0.0.1:{port}").parse().unwrap(), ..Default::default() } } /// Disable the endpoints pub fn disabled(mut self) -> Self { self.enabled = false; self } } /// Recursively walk a JSON value and redact fields with sensitive names fn redact_sensitive_fields(value: &mut Value) { match value { Value::Object(map) => { for (key, val) in map.iter_mut() { let key_lower = key.to_lowercase(); let is_sensitive = SENSITIVE_FIELD_PATTERNS .iter() .any(|pattern| key_lower.contains(pattern)); if is_sensitive { *val = Value::String("...".to_string()); } else { redact_sensitive_fields(val); } } } Value::Array(arr) => { for item in arr { redact_sensitive_fields(item); } } _ => {} } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/systeminit/si'

If you have feedback or need assistance with the MCP directory API, please join our Discord server