91 lines
2.5 KiB
Rust
91 lines
2.5 KiB
Rust
|
|
use clap::Parser;
|
||
|
|
use tracing_subscriber::EnvFilter;
|
||
|
|
use anyhow::Result;
|
||
|
|
|
||
|
|
use rustproxy::RustProxy;
|
||
|
|
use rustproxy::management;
|
||
|
|
use rustproxy_config::RustProxyOptions;
|
||
|
|
|
||
|
|
/// RustProxy - High-performance multi-protocol proxy
|
||
|
|
#[derive(Parser, Debug)]
|
||
|
|
#[command(name = "rustproxy", version, about)]
|
||
|
|
struct Cli {
|
||
|
|
/// Path to JSON configuration file
|
||
|
|
#[arg(short, long, default_value = "config.json")]
|
||
|
|
config: String,
|
||
|
|
|
||
|
|
/// Log level (trace, debug, info, warn, error)
|
||
|
|
#[arg(short, long, default_value = "info")]
|
||
|
|
log_level: String,
|
||
|
|
|
||
|
|
/// Validate configuration without starting
|
||
|
|
#[arg(long)]
|
||
|
|
validate: bool,
|
||
|
|
|
||
|
|
/// Run in management mode (JSON-over-stdin IPC for TypeScript wrapper)
|
||
|
|
#[arg(long)]
|
||
|
|
management: bool,
|
||
|
|
}
|
||
|
|
|
||
|
|
#[tokio::main]
|
||
|
|
async fn main() -> Result<()> {
|
||
|
|
let cli = Cli::parse();
|
||
|
|
|
||
|
|
// Initialize tracing - write to stderr so stdout is reserved for management IPC
|
||
|
|
tracing_subscriber::fmt()
|
||
|
|
.with_writer(std::io::stderr)
|
||
|
|
.with_env_filter(
|
||
|
|
EnvFilter::try_from_default_env()
|
||
|
|
.unwrap_or_else(|_| EnvFilter::new(&cli.log_level))
|
||
|
|
)
|
||
|
|
.init();
|
||
|
|
|
||
|
|
// Management mode: JSON IPC over stdin/stdout
|
||
|
|
if cli.management {
|
||
|
|
tracing::info!("RustProxy starting in management mode...");
|
||
|
|
return management::management_loop().await;
|
||
|
|
}
|
||
|
|
|
||
|
|
tracing::info!("RustProxy starting...");
|
||
|
|
|
||
|
|
// Load configuration
|
||
|
|
let options = RustProxyOptions::from_file(&cli.config)
|
||
|
|
.map_err(|e| anyhow::anyhow!("Failed to load config '{}': {}", cli.config, e))?;
|
||
|
|
|
||
|
|
tracing::info!(
|
||
|
|
"Loaded {} routes from {}",
|
||
|
|
options.routes.len(),
|
||
|
|
cli.config
|
||
|
|
);
|
||
|
|
|
||
|
|
// Validate-only mode
|
||
|
|
if cli.validate {
|
||
|
|
match rustproxy_config::validate_routes(&options.routes) {
|
||
|
|
Ok(()) => {
|
||
|
|
tracing::info!("Configuration is valid");
|
||
|
|
return Ok(());
|
||
|
|
}
|
||
|
|
Err(errors) => {
|
||
|
|
for err in &errors {
|
||
|
|
tracing::error!("Validation error: {}", err);
|
||
|
|
}
|
||
|
|
anyhow::bail!("{} validation errors found", errors.len());
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Create and start proxy
|
||
|
|
let mut proxy = RustProxy::new(options)?;
|
||
|
|
proxy.start().await?;
|
||
|
|
|
||
|
|
// Wait for shutdown signal
|
||
|
|
tracing::info!("RustProxy is running. Press Ctrl+C to stop.");
|
||
|
|
tokio::signal::ctrl_c().await?;
|
||
|
|
|
||
|
|
tracing::info!("Shutdown signal received");
|
||
|
|
proxy.stop().await?;
|
||
|
|
|
||
|
|
tracing::info!("RustProxy shutdown complete");
|
||
|
|
Ok(())
|
||
|
|
}
|