use clap::{Parser, Subcommand, ValueEnum};
#[derive(Copy, Clone, Debug, PartialEq, Eq, ValueEnum)]
pub enum LogFormat {
Pretty,
Compact,
Json,
}
impl LogFormat {
pub const fn as_str(self) -> &'static str {
match self {
LogFormat::Pretty => "pretty",
LogFormat::Compact => "compact",
LogFormat::Json => "json",
}
}
}
impl std::fmt::Display for LogFormat {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(self.as_str())
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, ValueEnum)]
pub enum UpstreamTestMode {
Proxy,
Tcp,
}
impl UpstreamTestMode {
pub const fn as_str(self) -> &'static str {
match self {
UpstreamTestMode::Proxy => "proxy",
UpstreamTestMode::Tcp => "tcp",
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, ValueEnum)]
pub enum RouteProtocol {
Http,
Socks4,
Socks5,
}
impl RouteProtocol {
pub const fn as_str(self) -> &'static str {
match self {
RouteProtocol::Http => "http",
RouteProtocol::Socks4 => "socks4",
RouteProtocol::Socks5 => "socks5",
}
}
pub const fn to_protocol_id(self) -> eggress_core::ProtocolId {
match self {
RouteProtocol::Http => eggress_core::ProtocolId::Http,
RouteProtocol::Socks4 => eggress_core::ProtocolId::Socks4,
RouteProtocol::Socks5 => eggress_core::ProtocolId::Socks5,
}
}
}
#[derive(Parser, Debug)]
#[command(name = "eggress", version, about = "A multi-protocol TCP proxy")]
pub struct Cli {
#[arg(short = 'l', long = "listen", value_name = "URI")]
pub listeners: Vec<String>,
#[arg(short = 'r', long = "remote", value_name = "URI")]
pub upstreams: Vec<String>,
#[arg(long = "log-format", value_enum, default_value_t = LogFormat::Pretty)]
pub log_format: LogFormat,
#[arg(short = 'c', long = "config", global = true, value_name = "PATH")]
pub config: Option<String>,
#[arg(long = "rules-file", value_name = "PATH")]
pub rules_file: Option<String>,
#[command(subcommand)]
pub command: Option<SubCommand>,
}
#[derive(Subcommand, Debug)]
pub enum SubCommand {
Version,
Route(RouteExplain),
Upstream(UpstreamCommand),
Update(UpdateArgs),
#[cfg(feature = "pproxy-compat")]
Pproxy(PproxyCommand),
#[cfg(feature = "operations")]
SystemProxy(SystemProxyCommand),
}
#[derive(Parser, Debug)]
pub struct UpdateArgs {}
#[derive(Parser, Debug)]
pub struct UpstreamCommand {
#[command(subcommand)]
pub action: UpstreamAction,
}
#[derive(Subcommand, Debug)]
pub enum UpstreamAction {
Test(UpstreamTest),
}
#[derive(Parser, Debug)]
pub struct UpstreamTest {
#[arg(short, long, value_name = "ID")]
pub id: Option<String>,
#[arg(short, long, value_name = "HOST:PORT")]
pub target: Option<String>,
#[arg(long, default_value = "5")]
pub timeout: u64,
#[arg(long, value_enum, default_value_t = UpstreamTestMode::Proxy)]
pub mode: UpstreamTestMode,
#[arg(long)]
pub json: bool,
}
#[derive(Parser, Debug)]
pub struct RouteExplain {
pub target: String,
#[arg(long)]
pub listener: Option<String>,
#[arg(long, value_enum)]
pub protocol: Option<RouteProtocol>,
#[arg(long)]
pub json: bool,
#[arg(long, value_name = "URL")]
pub admin: Option<String>,
}
#[cfg(feature = "pproxy-compat")]
#[derive(Parser, Debug)]
pub struct PproxyCommand {
#[command(subcommand)]
pub action: PproxyAction,
}
#[cfg(feature = "pproxy-compat")]
#[derive(Subcommand, Debug)]
pub enum PproxyAction {
Translate(PproxyTranslate),
Check(PproxyCheck),
Run(PproxyRun),
}
#[cfg(feature = "pproxy-compat")]
#[derive(Parser, Debug)]
pub struct PproxyTranslate {
#[arg(trailing_var_arg = true, allow_hyphen_values = true)]
pub args: Vec<String>,
#[arg(long)]
pub annotate: bool,
}
#[cfg(feature = "pproxy-compat")]
#[derive(Parser, Debug)]
pub struct PproxyCheck {
#[arg(trailing_var_arg = true, allow_hyphen_values = true)]
pub args: Vec<String>,
#[arg(long)]
pub json: bool,
}
#[cfg(feature = "pproxy-compat")]
#[derive(Parser, Debug)]
pub struct PproxyRun {
#[arg(trailing_var_arg = true, allow_hyphen_values = true)]
pub args: Vec<String>,
#[arg(long = "log-format", value_enum, default_value_t = LogFormat::Pretty)]
pub log_format: LogFormat,
}
#[cfg(feature = "operations")]
#[derive(Parser, Debug)]
pub struct SystemProxyCommand {
#[command(subcommand)]
pub action: SystemProxyAction,
}
#[cfg(feature = "operations")]
#[derive(Subcommand, Debug)]
pub enum SystemProxyAction {
Inspect(SystemProxyInspect),
}
#[cfg(feature = "operations")]
#[derive(Parser, Debug)]
pub struct SystemProxyInspect {
#[arg(long)]
pub json: bool,
}
#[derive(Debug, Clone)]
pub struct CliContext {
pub config: Option<String>,
pub log_format: LogFormat,
}
impl CliContext {
pub fn from_cli(cli: &Cli) -> Self {
Self {
config: cli.config.clone(),
log_format: cli.log_format,
}
}
}