use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::path::Path;
use super::auth::AuthConfig;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct HttpValidationConfig {
pub mode: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct HttpCorsConfig {
pub enabled: bool,
#[serde(default)]
pub allowed_origins: Vec<String>,
#[serde(default)]
pub allowed_methods: Vec<String>,
#[serde(default)]
pub allowed_headers: Vec<String>,
#[serde(default = "default_cors_allow_credentials")]
pub allow_credentials: bool,
}
fn default_cors_allow_credentials() -> bool {
false
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
pub struct HttpConfig {
pub enabled: bool,
pub port: u16,
pub host: String,
pub openapi_spec: Option<String>,
pub cors: Option<HttpCorsConfig>,
pub request_timeout_secs: u64,
pub validation: Option<HttpValidationConfig>,
pub aggregate_validation_errors: bool,
pub validate_responses: bool,
pub response_template_expand: bool,
pub validation_status: Option<u16>,
pub validation_overrides: HashMap<String, String>,
pub skip_admin_validation: bool,
pub auth: Option<AuthConfig>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tls: Option<HttpTlsConfig>,
}
impl Default for HttpConfig {
fn default() -> Self {
Self {
enabled: true,
port: 3000,
host: "0.0.0.0".to_string(),
openapi_spec: None,
cors: Some(HttpCorsConfig {
enabled: true,
allowed_origins: vec!["*".to_string()],
allowed_methods: vec![
"GET".to_string(),
"POST".to_string(),
"PUT".to_string(),
"DELETE".to_string(),
"PATCH".to_string(),
"OPTIONS".to_string(),
],
allowed_headers: vec!["content-type".to_string(), "authorization".to_string()],
allow_credentials: false, }),
request_timeout_secs: 30,
validation: Some(HttpValidationConfig {
mode: "enforce".to_string(),
}),
aggregate_validation_errors: true,
validate_responses: false,
response_template_expand: false,
validation_status: None,
validation_overrides: HashMap::new(),
skip_admin_validation: true,
auth: None,
tls: None,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct HttpTlsConfig {
pub enabled: bool,
pub cert_file: String,
pub key_file: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub ca_file: Option<String>,
#[serde(default = "default_tls_min_version")]
pub min_version: String,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub cipher_suites: Vec<String>,
#[serde(default)]
pub require_client_cert: bool,
#[serde(default = "default_mtls_mode")]
pub mtls_mode: String,
}
fn default_mtls_mode() -> String {
"off".to_string()
}
fn default_tls_min_version() -> String {
"1.2".to_string()
}
impl Default for HttpTlsConfig {
fn default() -> Self {
Self {
enabled: true,
cert_file: String::new(),
key_file: String::new(),
ca_file: None,
min_version: "1.2".to_string(),
cipher_suites: Vec::new(),
require_client_cert: false,
mtls_mode: "off".to_string(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
pub struct WebSocketConfig {
pub enabled: bool,
pub port: u16,
pub host: String,
pub replay_file: Option<String>,
pub connection_timeout_secs: u64,
}
impl Default for WebSocketConfig {
fn default() -> Self {
Self {
enabled: true,
port: 3001,
host: "0.0.0.0".to_string(),
replay_file: None,
connection_timeout_secs: 300,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
pub struct GrpcConfig {
pub enabled: bool,
pub port: u16,
pub host: String,
pub proto_dir: Option<String>,
pub tls: Option<TlsConfig>,
}
impl Default for GrpcConfig {
fn default() -> Self {
Self {
enabled: true,
port: 50051,
host: "0.0.0.0".to_string(),
proto_dir: None,
tls: None,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
pub struct GraphQLConfig {
pub enabled: bool,
pub port: u16,
pub host: String,
pub schema_path: Option<String>,
pub handlers_dir: Option<String>,
pub playground_enabled: bool,
pub upstream_url: Option<String>,
pub introspection_enabled: bool,
}
impl Default for GraphQLConfig {
fn default() -> Self {
Self {
enabled: true,
port: 4000,
host: "0.0.0.0".to_string(),
schema_path: None,
handlers_dir: None,
playground_enabled: true,
upstream_url: None,
introspection_enabled: true,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct TlsConfig {
pub cert_path: String,
pub key_path: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct MqttConfig {
pub enabled: bool,
pub port: u16,
pub host: String,
pub max_connections: usize,
pub max_packet_size: usize,
pub keep_alive_secs: u16,
pub fixtures_dir: Option<std::path::PathBuf>,
pub enable_retained_messages: bool,
pub max_retained_messages: usize,
}
impl Default for MqttConfig {
fn default() -> Self {
Self {
enabled: false,
port: 1883,
host: "0.0.0.0".to_string(),
max_connections: 1000,
max_packet_size: 268435456, keep_alive_secs: 60,
fixtures_dir: None,
enable_retained_messages: true,
max_retained_messages: 10000,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct SmtpConfig {
pub enabled: bool,
pub port: u16,
pub host: String,
pub hostname: String,
pub fixtures_dir: Option<std::path::PathBuf>,
pub timeout_secs: u64,
pub max_connections: usize,
pub enable_mailbox: bool,
pub max_mailbox_messages: usize,
pub enable_starttls: bool,
pub tls_cert_path: Option<std::path::PathBuf>,
pub tls_key_path: Option<std::path::PathBuf>,
}
impl Default for SmtpConfig {
fn default() -> Self {
Self {
enabled: false,
port: 1025,
host: "0.0.0.0".to_string(),
hostname: "mockforge-smtp".to_string(),
fixtures_dir: Some(std::path::PathBuf::from("./fixtures/smtp")),
timeout_secs: 300,
max_connections: 10,
enable_mailbox: true,
max_mailbox_messages: 1000,
enable_starttls: false,
tls_cert_path: None,
tls_key_path: None,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct FtpConfig {
pub enabled: bool,
pub port: u16,
pub host: String,
pub passive_ports: (u16, u16),
pub max_connections: usize,
pub timeout_secs: u64,
pub allow_anonymous: bool,
pub fixtures_dir: Option<std::path::PathBuf>,
pub virtual_root: std::path::PathBuf,
}
impl Default for FtpConfig {
fn default() -> Self {
Self {
enabled: false,
port: 2121,
host: "0.0.0.0".to_string(),
passive_ports: (50000, 51000),
max_connections: 100,
timeout_secs: 300,
allow_anonymous: true,
fixtures_dir: None,
virtual_root: std::path::PathBuf::from("/mockforge"),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct KafkaConfig {
pub enabled: bool,
pub port: u16,
pub host: String,
pub broker_id: i32,
pub max_connections: usize,
pub log_retention_ms: i64,
pub log_segment_bytes: i64,
pub fixtures_dir: Option<std::path::PathBuf>,
pub auto_create_topics: bool,
pub default_partitions: i32,
pub default_replication_factor: i16,
}
impl Default for KafkaConfig {
fn default() -> Self {
Self {
enabled: false,
port: 9092, host: "0.0.0.0".to_string(),
broker_id: 1,
max_connections: 1000,
log_retention_ms: 604800000, log_segment_bytes: 1073741824, fixtures_dir: None,
auto_create_topics: true,
default_partitions: 3,
default_replication_factor: 1,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct AmqpConfig {
pub enabled: bool,
pub port: u16,
pub host: String,
pub max_connections: usize,
pub max_channels_per_connection: u16,
pub frame_max: u32,
pub heartbeat_interval: u16,
pub fixtures_dir: Option<std::path::PathBuf>,
pub virtual_hosts: Vec<String>,
pub tls_enabled: bool,
pub tls_port: u16,
pub tls_cert_path: Option<std::path::PathBuf>,
pub tls_key_path: Option<std::path::PathBuf>,
pub tls_ca_path: Option<std::path::PathBuf>,
pub tls_client_auth: bool,
}
impl Default for AmqpConfig {
fn default() -> Self {
Self {
enabled: false,
port: 5672, host: "0.0.0.0".to_string(),
max_connections: 1000,
max_channels_per_connection: 100,
frame_max: 131072, heartbeat_interval: 60,
fixtures_dir: None,
virtual_hosts: vec!["/".to_string()],
tls_enabled: false,
tls_port: 5671, tls_cert_path: None,
tls_key_path: None,
tls_ca_path: None,
tls_client_auth: false,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct TcpConfig {
pub enabled: bool,
pub port: u16,
pub host: String,
pub max_connections: usize,
pub timeout_secs: u64,
pub fixtures_dir: Option<std::path::PathBuf>,
pub echo_mode: bool,
pub enable_tls: bool,
pub tls_cert_path: Option<std::path::PathBuf>,
pub tls_key_path: Option<std::path::PathBuf>,
}
impl Default for TcpConfig {
fn default() -> Self {
Self {
enabled: false,
port: 9999,
host: "0.0.0.0".to_string(),
max_connections: 1000,
timeout_secs: 300,
fixtures_dir: Some(std::path::PathBuf::from("./fixtures/tcp")),
echo_mode: true,
enable_tls: false,
tls_cert_path: None,
tls_key_path: None,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
pub struct AdminConfig {
pub enabled: bool,
pub port: u16,
pub host: String,
pub auth_required: bool,
pub username: Option<String>,
pub password: Option<String>,
pub mount_path: Option<String>,
pub api_enabled: bool,
pub prometheus_url: String,
}
impl Default for AdminConfig {
fn default() -> Self {
let default_host = if std::env::var("DOCKER_CONTAINER").is_ok()
|| std::env::var("container").is_ok()
|| Path::new("/.dockerenv").exists()
{
"0.0.0.0".to_string()
} else {
"127.0.0.1".to_string()
};
Self {
enabled: false,
port: 9080,
host: default_host,
auth_required: false,
username: None,
password: None,
mount_path: None,
api_enabled: true,
prometheus_url: "http://localhost:9090".to_string(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct ProtocolConfig {
pub enabled: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct ProtocolsConfig {
pub http: ProtocolConfig,
pub graphql: ProtocolConfig,
pub grpc: ProtocolConfig,
pub websocket: ProtocolConfig,
pub smtp: ProtocolConfig,
pub mqtt: ProtocolConfig,
pub ftp: ProtocolConfig,
pub kafka: ProtocolConfig,
pub rabbitmq: ProtocolConfig,
pub amqp: ProtocolConfig,
pub tcp: ProtocolConfig,
}
impl Default for ProtocolsConfig {
fn default() -> Self {
Self {
http: ProtocolConfig { enabled: true },
graphql: ProtocolConfig { enabled: true },
grpc: ProtocolConfig { enabled: true },
websocket: ProtocolConfig { enabled: true },
smtp: ProtocolConfig { enabled: false },
mqtt: ProtocolConfig { enabled: true },
ftp: ProtocolConfig { enabled: false },
kafka: ProtocolConfig { enabled: false },
rabbitmq: ProtocolConfig { enabled: false },
amqp: ProtocolConfig { enabled: false },
tcp: ProtocolConfig { enabled: false },
}
}
}