use crate::config::config_runtime::RateLimitConfig;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::path::PathBuf;
use validator::{Validate, ValidationError};
#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
pub struct ServerSettings {
#[validate(range(min = 1, max = 65535))]
pub port: u16,
#[validate(length(min = 1))]
pub host: String,
pub admin_ui: bool,
pub cors: bool,
#[validate(range(min = 1))]
pub max_connections: usize,
#[validate(range(min = 1))]
pub request_timeout_secs: u64,
#[validate(range(min = 1))]
pub graceful_shutdown_timeout_secs: u64,
pub tls: Option<TlsConfig>,
#[serde(default)]
pub backup_directory: Option<PathBuf>,
#[serde(skip)]
pub config_file: Option<PathBuf>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
pub struct TlsConfig {
#[validate(custom(function = "validate_path"))]
pub cert_path: PathBuf,
#[validate(custom(function = "validate_path"))]
pub key_path: PathBuf,
pub require_client_cert: bool,
pub ca_cert_path: Option<PathBuf>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
pub struct HttpProtocolSettings {
#[serde(default = "default_true")]
pub http2_enabled: bool,
#[serde(default)]
pub http3_enabled: bool,
#[serde(default = "default_http2_connection_window")]
#[validate(range(min = 65535, max = 16777216))]
pub http2_initial_connection_window_size: u32,
#[serde(default = "default_http2_stream_window")]
#[validate(range(min = 65535, max = 16777216))]
pub http2_initial_stream_window_size: u32,
#[serde(default = "default_http2_max_streams")]
#[validate(range(min = 1, max = 1000))]
pub http2_max_concurrent_streams: u32,
#[serde(default = "default_http2_frame_size")]
#[validate(range(min = 16384, max = 16777215))]
pub http2_max_frame_size: u32,
#[serde(default = "default_http2_keepalive")]
#[validate(range(min = 1))]
pub http2_keep_alive_interval_secs: u64,
#[serde(default = "default_http2_keepalive_timeout")]
#[validate(range(min = 1))]
pub http2_keep_alive_timeout_secs: u64,
#[serde(default)]
pub enable_server_push: bool,
#[serde(default = "default_true")]
pub enable_header_compression: bool,
#[serde(default = "default_true")]
pub sparql_optimized: bool,
}
fn default_true() -> bool {
true
}
fn default_http2_connection_window() -> u32 {
1024 * 1024 }
fn default_http2_stream_window() -> u32 {
256 * 1024 }
fn default_http2_max_streams() -> u32 {
100
}
fn default_http2_frame_size() -> u32 {
16384 }
fn default_http2_keepalive() -> u64 {
60 }
fn default_http2_keepalive_timeout() -> u64 {
20 }
impl Default for HttpProtocolSettings {
fn default() -> Self {
Self {
http2_enabled: true,
http3_enabled: false,
http2_initial_connection_window_size: default_http2_connection_window(),
http2_initial_stream_window_size: default_http2_stream_window(),
http2_max_concurrent_streams: default_http2_max_streams(),
http2_max_frame_size: default_http2_frame_size(),
http2_keep_alive_interval_secs: default_http2_keepalive(),
http2_keep_alive_timeout_secs: default_http2_keepalive_timeout(),
enable_server_push: false,
enable_header_compression: true,
sparql_optimized: true,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
pub struct DatasetConfig {
#[validate(length(min = 1))]
pub name: String,
#[validate(length(min = 1))]
pub location: String,
pub read_only: bool,
#[validate(nested)]
pub text_index: Option<TextIndexConfig>,
pub shacl_shapes: Vec<PathBuf>,
#[validate(nested)]
pub services: Vec<ServiceConfig>,
#[validate(nested)]
pub access_control: Option<AccessControlConfig>,
pub backup: Option<BackupConfig>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
pub struct ServiceConfig {
#[validate(length(min = 1))]
pub name: String,
pub service_type: ServiceType,
#[validate(length(min = 1))]
pub endpoint: String,
pub auth_required: bool,
pub rate_limit: Option<RateLimitConfig>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ServiceType {
SparqlQuery,
SparqlUpdate,
GraphStore,
GraphQL,
Rest,
}
#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
pub struct AccessControlConfig {
pub read_roles: Vec<String>,
pub write_roles: Vec<String>,
pub admin_roles: Vec<String>,
pub public_read: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
pub struct BackupConfig {
pub enabled: bool,
pub directory: PathBuf,
#[validate(range(min = 1))]
pub interval_hours: u64,
#[validate(range(min = 1))]
pub retain_count: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
pub struct TextIndexConfig {
pub enabled: bool,
#[validate(length(min = 1))]
pub analyzer: String,
#[validate(range(min = 1))]
pub max_results: usize,
pub stemming: bool,
pub stop_words: Vec<String>,
}
pub type DatasetMap = HashMap<String, DatasetConfig>;
fn validate_path(path: &std::path::Path) -> Result<(), ValidationError> {
if path.as_os_str().is_empty() {
return Err(ValidationError::new("path_empty"));
}
Ok(())
}