use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RouterConfig {
pub server: ServerConfig,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ServerConfig {
pub protocols: Vec<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub rest: Option<RestConfig>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub graphql: Option<GraphQLConfig>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub grpc: Option<GrpcConfig>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RestConfig {
#[serde(default = "default_rest_port")]
pub port: u16,
#[serde(default = "default_rest_prefix")]
pub path_prefix: String,
}
fn default_rest_port() -> u16 {
8080
}
fn default_rest_prefix() -> String {
"/api/v1".to_string()
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GraphQLConfig {
#[serde(default = "default_graphql_port")]
pub port: u16,
#[serde(default = "default_graphql_path")]
pub path: String,
#[serde(default)]
pub playground: bool,
}
fn default_graphql_port() -> u16 {
8081
}
fn default_graphql_path() -> String {
"/graphql".to_string()
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GrpcConfig {
#[serde(default = "default_grpc_port")]
pub port: u16,
#[serde(default)]
pub reflection: bool,
}
fn default_grpc_port() -> u16 {
9090
}
impl RouterConfig {
pub fn from_toml(toml: &str) -> Result<Self, String> {
toml::from_str(toml).map_err(|e| format!("Failed to parse config: {}", e))
}
pub fn from_file(path: &str) -> Result<Self, String> {
let contents =
std::fs::read_to_string(path).map_err(|e| format!("Failed to read file: {}", e))?;
Self::from_toml(&contents)
}
pub fn protocols(&self) -> &[String] {
&self.server.protocols
}
pub fn has_protocol(&self, protocol: &str) -> bool {
self.server.protocols.contains(&protocol.to_string())
}
pub fn rest(&self) -> Option<&RestConfig> {
self.server.rest.as_ref()
}
pub fn graphql(&self) -> Option<&GraphQLConfig> {
self.server.graphql.as_ref()
}
pub fn grpc(&self) -> Option<&GrpcConfig> {
self.server.grpc.as_ref()
}
}
impl RestConfig {
pub fn port(&self) -> u16 {
self.port
}
pub fn path_prefix(&self) -> &str {
&self.path_prefix
}
}
impl GraphQLConfig {
pub fn port(&self) -> u16 {
self.port
}
pub fn path(&self) -> &str {
&self.path
}
pub fn playground(&self) -> bool {
self.playground
}
}
impl GrpcConfig {
pub fn port(&self) -> u16 {
self.port
}
pub fn reflection(&self) -> bool {
self.reflection
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_basic_config() {
let toml = r#"
[server]
protocols = ["rest", "graphql"]
"#;
let config = RouterConfig::from_toml(toml).unwrap();
assert_eq!(config.protocols().len(), 2);
assert!(config.has_protocol("rest"));
assert!(config.has_protocol("graphql"));
assert!(!config.has_protocol("grpc"));
}
#[test]
fn test_parse_full_config() {
let toml = r#"
[server]
protocols = ["rest", "graphql", "grpc"]
[server.rest]
port = 8080
path_prefix = "/api/v1"
[server.graphql]
port = 8081
path = "/graphql"
playground = true
[server.grpc]
port = 9090
reflection = true
"#;
let config = RouterConfig::from_toml(toml).unwrap();
assert_eq!(config.protocols().len(), 3);
assert!(config.has_protocol("rest"));
assert!(config.has_protocol("graphql"));
assert!(config.has_protocol("grpc"));
let rest = config.rest().unwrap();
assert_eq!(rest.port(), 8080);
assert_eq!(rest.path_prefix(), "/api/v1");
let graphql = config.graphql().unwrap();
assert_eq!(graphql.port(), 8081);
assert_eq!(graphql.path(), "/graphql");
assert!(graphql.playground());
let grpc = config.grpc().unwrap();
assert_eq!(grpc.port(), 9090);
assert!(grpc.reflection());
}
#[test]
fn test_parse_minimal_config() {
let toml = r#"
[server]
protocols = ["rest"]
"#;
let config = RouterConfig::from_toml(toml).unwrap();
assert_eq!(config.protocols().len(), 1);
assert!(config.has_protocol("rest"));
assert!(config.rest().is_none()); }
#[test]
fn test_default_values() {
let toml = r#"
[server]
protocols = ["rest", "graphql", "grpc"]
[server.rest]
[server.graphql]
[server.grpc]
"#;
let config = RouterConfig::from_toml(toml).unwrap();
let rest = config.rest().unwrap();
assert_eq!(rest.port(), 8080);
assert_eq!(rest.path_prefix(), "/api/v1");
let graphql = config.graphql().unwrap();
assert_eq!(graphql.port(), 8081);
assert_eq!(graphql.path(), "/graphql");
assert!(!graphql.playground());
let grpc = config.grpc().unwrap();
assert_eq!(grpc.port(), 9090);
assert!(!grpc.reflection()); }
}