写点什么

从零开始用 Rust 编写 nginx,命令行参数的设计与解析及说明

  • 2024-01-24
    福建
  • 本文字数:6178 字

    阅读完需:约 20 分钟

wmproxy


wmproxy已用Rust实现http/https代理, socks5代理, 反向代理, 静态文件服务器,四层 TCP/UDP 转发,七层负载均衡,内网穿透,后续将实现websocket代理等,会将实现过程分享出来,感兴趣的可以一起造个轮子


项目地址


国内: https://gitee.com/tickbh/wmproxy


github: https://github.com/tickbh/wmproxy


设计目标


设置启动命令行参数方便在没有配置的情况下启动。


设计事项


当你在 Linux 终端上输入 git --help 时,你会看到这样的打印:


shell> git --helpusage: git [--version] [--help] [-C <path>] [-c <name>=<value>]           [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]           [-p | --paginate | --no-pager] [--no-replace-objects] [--bare]           [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]           <command> [<args>] These are common Git commands used in various situations: start a working area (see also: git help tutorial)   clone      Clone a repository into a new directory   init       Create an empty Git repository or reinitialize an existing one...... <omitted>
复制代码


Git 程序支持一长串参数。我们以它为例来讨论程序的参数应该是什么样的。


为了给用户给予一个良好的命令行界面,程序的参数处理部分应该支持以下功能:


  • 接受参数的选项

  • 不带任何参数的标志/开关

  • 长名称(以双连字符开头,如--paginate)和短名称(以单连字符开头,如-p)

  • 友好的帮助信息--help

  • 子命令(如 git add)


通过命令行我们可以执行程序中的非常多的功能,也就是命令行让程序可以在无需 GUI 的情况下拥有无限丰富的功能。


RUST 中的命令行解析


在这里以 bpaf 来举例,也是本项目中选择的命令行解析库,相对来说他支持宏的同时也支持比较丰富的程序中的组合,也拥有较多的 demo 可以参考如何使用:


use bpaf::{short, Bpaf, Parser};use std::path::PathBuf; #[derive(Debug, Clone, Bpaf)]#[bpaf(options, version)]#[allow(dead_code)]struct Opts {    /// 是否开始调试模式    #[bpaf(short, long)]    debug: bool,    /// 这是一个注释,将被忽略    #[bpaf(external(verbose))]    verbose: usize,    /// 设置速度, 拥有默认速度    #[bpaf(argument("SPEED"), fallback(42.0), display_fallback)]    speed: f64,    /// 输出目录    output: PathBuf,     /// 将检测必须为正数    #[bpaf(guard(positive, "must be positive"), fallback(1))]    nb_cars: u32,    files_to_process: Vec<PathBuf>,} fn verbose() -> impl Parser<usize> {    // number of occurrences of the v/verbose flag capped at 3    short('v')        .long("verbose")        .help("启动verbose模式\n根据输入的v的个数来判定等级\n可以 -v -v -v 或者 -vvv")        .req_flag(())        .many()        .map(|xs| xs.len())        .guard(|&x| x <= 3, "最多仅能输入三个v")} fn positive(input: &u32) -> bool {    *input > 1} fn main() {    println!("{:#?}", opts().run());}
复制代码


通过启动打印--help 信息可知cargo run --example arg -- --help


PS D:\my\wmproxy> cargo run --example arg -- --help   Compiling wmproxy v0.2.5 (D:\my\wmproxy)    Finished dev [unoptimized + debuginfo] target(s) in 1.12s     Running `target\debug\examples\arg.exe --help`Usage: arg.exe [-d] [-v]... [--speed=SPEED] --output=ARG [--nb-cars=ARG] [--files-to-process=ARG]... Available options:    -d, --debug        是否开始调试模式    -v, --verbose      启动verbose模式 根据输入的v的个数来判定等级 可以 -v -v -v 或者 -vvv                --speed=SPEED  设置速度, 拥有默认速度                       [default: 42]        --output=ARG   输出目录        --nb-cars=ARG  将检测必须为正数        --files-to-process=ARG    -h, --help         Prints help information    -V, --version      Prints version information
复制代码


我们可以通过简单的配置来拥有较完整的命令行的模式的支持,包括默认参数fallback,及完整的 help 信息。


rust 中还有其它较为知名的解析库,图片来源于网上,可根据项目的需要进行相应的选择。



命令行参数


该项目选择用的是子命令的模式


  • wmproxy run 启动命令

  • wmproxy start 启动命令, 但在后台运行

  • wmproxy stop 关闭命令

  • wmproxy reload 进行重载配置

  • wmproxy check 检查配置是否正确

  • wmproxy proxy 代理及内网穿透相关功能

  • wmproxy file-server 启动文件服务器

  • wmproxy reverse-proxy 启动负载均衡服务器

  • wmproxy ws-proxy Websocket 协议转发相关

  • wmproxy version 打印当前版本号


wmproxy


通过命令wmproxy run --help可以得到


Usage: wmproxy.exe run -c=ARG [--pidfile=ARG] [--control=ARG] [--disable-stdout] [--disable-control][-v] [--default-level=ARG] Available options:    -c, --config=ARG         配置文件路径        --pidfile=ARG        写入进程id文件        --control=ARG        输入控制台的监听地址                             [default: 127.0.0.1:8837]        --disable-stdout     禁用默认输出        --disable-control    禁用控制微端    -v, --verbose            是否显示更多日志        --default-level=ARG  设置默认等级    -h, --help               Prints help information
复制代码


通过配置文件启动程序如:


wmproxy run -c config/reverse.toml
复制代码


wmproxy start


通过命令wmproxy start --help可以得到


Usage: wmproxy.exe start -c=ARG [--pidfile=ARG] [--control=ARG] [--disable-stdout] [--disable-control][-v] [--default-level=ARG] Available options:    -c, --config=ARG         配置文件路径        --pidfile=ARG        写入进程id文件        --control=ARG        输入控制台的监听地址                             [default: 127.0.0.1:8837]        --disable-stdout     禁用默认输出        --disable-control    禁用控制微端    -v, --verbose            是否显示更多日志        --default-level=ARG  设置默认等级    -h, --help               Prints help information
复制代码


通过配置文件启动程序,我们通过观察可以得知参数与 run 一模一样,差别是该参数将后台启动。示例如:


wmproxy start -c config/reverse.toml
复制代码

wmproxy stop


通过命令wmproxy stop --help可以得到


Usage: wmproxy.exe stop [-c=ARG] [-p=ARG] [-u=ARG] [--control=ARG] [--disable-stdout] [--disable-control] [-v] [--default-level=ARG] Available options:    -c, --config=ARG         配置文件路径    -p, --pidfile=ARG        写入进程id文件    -u, --url=ARG            控制微端地址        --control=ARG        输入控制台的监听地址                             [default: 127.0.0.1:8837]        --disable-stdout     禁用默认输出        --disable-control    禁用控制微端    -v, --verbose            是否显示更多日志        --default-level=ARG  设置默认等级    -h, --help               Prints help information
复制代码


此处我们通过三种方式将其关闭,一种是配置文件,一种是 pid 文件,一种是控制微端的 url。示例如:


wmproxy stop -c config/reverse.toml或者wmproxy stop -p wmproxy.pid或者wmproxy stop -u http://127.0.0.1:8837
复制代码

wmproxy reload


通过命令wmproxy reload --help可以得到


Usage: wmproxy.exe reload [-c=ARG] [-u=ARG] [--control=ARG] [--disable-stdout] [--disable-control] [-v] [--default-level=ARG] Available options:    -c, --config=ARG         配置文件路径    -u, --url=ARG            控制微端地址        --control=ARG        输入控制台的监听地址                             [default: 127.0.0.1:8837]        --disable-stdout     禁用默认输出        --disable-control    禁用控制微端
复制代码


此处我们通过三种方式将其重载,一种是配置文件,一种是控制微端的 url。


示例如:


wmproxy reload -c config/reverse.toml或者wmproxy reload -u http://127.0.0.1:8837
复制代码

wmproxy proxy


代理类相对参数比较复杂通过命令wmproxy proxy --help可以得到


Usage: wmproxy.exe proxy [-b=ARG] [--flag=ARG] [--mode=ARG] [-S=ARG] [--user=ARG] [--pass=ARG] [--udp-bind=ARG] [--map-http-bind=ARG] [--map-https-bind=ARG] [--map-tcp-bind=ARG] [--map-proxy-bind=ARG] [--map-cert=ARG] [--map-key=ARG] [--center] [--ts] [--tc] [--two-way-tls] [--domain=ARG] [--cert=ARG] [--key=ARG] [--mappings=ARG]... [--control=ARG] [--disable-stdout] [--disable-control] [-v] [--default-level=ARG] 代理类, 一个代理类启动一种类型的代理    -b, --bind-addr=ARG       代理绑定端口地址                              [default: 127.0.0.1:8090]        --flag=ARG            代理种类, 如http https socks5        --mode=ARG            启动程序类型    -S, --server=ARG          连接代理服务端地址        --user=ARG            用于socks验证及中心服务器验证        --pass=ARG            用于socks验证及中心服务器验证        --udp-bind=ARG        udp的绑定地址        --map-http-bind=ARG   内网http的映射地址        --map-https-bind=ARG  内网https的映射地址        --map-tcp-bind=ARG    内网tcp的映射地址        --map-proxy-bind=ARG  内网代理的映射地址        --map-cert=ARG        内网映射的证书cert        --map-key=ARG         内网映射的证书key        --center              是否启用协议转发        --ts                  连接服务端是否启用tls        --tc                  接收客户端是否启用tls        --two-way-tls         双向认证是否启用        --domain=ARG          tls证书所用的域名        --cert=ARG            公开的证书公钥文件        --key=ARG             隐私的证书私钥文件        --mappings=ARG Available options:        --control=ARG         输入控制台的监听地址                              [default: 127.0.0.1:8837]        --disable-stdout      禁用默认输出        --disable-control     禁用控制微端    -v, --verbose             是否显示更多日志        --default-level=ARG   设置默认等级    -h, --help                Prints help information
复制代码


如果仅仅启动代理功能可以


wmproxy proxy -b="127.0.0.1:8090"或者wmproxy proxy -b "127.0.0.1:8090"
复制代码


即可启动 8090 开始的 http/https/socks5 代理

wmproxy file-server


启动文件服务通过命令wmproxy file-server --help可以得到


Usage: wmproxy.exe file-server [-r=ARG] [-l=ARG] [-d=ARG] [-b] [--access-log=ARG] [--control=ARG] [--disable-stdout] [--disable-control] [-v] [--default-level=ARG] Available options:    -r, --root=ARG           静态文件根目录路径    -l, --listen=ARG         监听地址                             [default: 127.0.0.1:80]    -d, --domain=ARG         域名地址    -b, --browse             是否支持目录        --access-log=ARG     访问日志放的位置如"logs/access.log trace"        --control=ARG        输入控制台的监听地址                             [default: 127.0.0.1:8837]        --disable-stdout     禁用默认输出        --disable-control    禁用控制微端    -v, --verbose            是否显示更多日志        --default-level=ARG  设置默认等级    -h, --help               Prints help information
复制代码


如果仅仅启动代理功能可以


wmproxy file-server或者wmproxy file-server -l :8080 -r "d:/my/wmproxy"
复制代码


即可启动文件服务器对其服务。

wmproxy reverse-proxy


启动负载均衡服务通过命令wmproxy reverse-proxy --help可以得到


Usage: wmproxy.exe reverse-proxy [-f=ARG] -t=ARG [-H=ARG]... [--access-log=ARG] [--tls] [--control=ARG] [--disable-stdout] [--disable-control] [-v] [--default-level=ARG] Available options:    -f, --from=ARG           负载均衡来源地址                             [default: 127.0.0.1:80]    -t, --to=ARG             负载均衡映射地址    -H, --header=ARG         头部信息修改如 "proxy x-forward-for {client_ip}"        --access-log=ARG     访问日志放的位置如"logs/access.log trace"        --tls                是否映射到https上        --control=ARG        输入控制台的监听地址                             [default: 127.0.0.1:8837]        --disable-stdout     禁用默认输出        --disable-control    禁用控制微端    -v, --verbose            是否显示更多日志        --default-level=ARG  设置默认等级    -h, --help               Prints help information
复制代码


需要配置从源目标到目标的信息,可以配置 header 等相应的信息。


wmproxy reverse-proxy或者wmproxy reverse-proxy -t :8080
复制代码


即可启动负载均衡服务对其服务。

wmproxy ws-proxy


启动 websocket 协议转发服务通过命令wmproxy ws-proxy --help可以得到


Usage: wmproxy.exe ws-proxy [-f=ARG] -t=ARG [--access-log=ARG] --mode=<ws2tcp,tcp2ws,tcp2wss> [--ws][--control=ARG] [--disable-stdout] [--disable-control] [-v] [--default-level=ARG] Available options:    -f, --from=ARG           负载均衡来源地址                             [default: 127.0.0.1:80]    -t, --to=ARG             负载均衡映射地址        --access-log=ARG     访问日志放的位置如"logs/access.log trace"        --mode=<ws2tcp,tcp2ws,tcp2wss>  当前代理的模式        --domain=ARG         当前域名        --ws                 是否支持websocket        --control=ARG        输入控制台的监听地址                             [default: 127.0.0.1:8837]
复制代码


模式中


  • ws2tcp 指 websocket 的流量转成 tcp

  • tcp2ws 指 tcp 的流量转成 websocket

  • tcp2wss 指 tcp 的流量转成 websocket tls 流量


# 将流量通过ws转成tcpwmproxy ws-proxy -t :8082 --mode ws2tcp或者# 将流量通过tcp转成wswmproxy ws-proxy -t :8099 --mode tcp2ws
复制代码


即可启动 websocket 的流量。


wmproxy version


打印当前软件的版本号

小结


好的命令行可以执行更强大的功能,也能让人更好的理解你的程序,这需要有一个好的帮助系统,也需要有一个强大的解析能力。此章讲述了命令行的执行功能,希望可以帮助到你的使用。


文章转载自:问蒙服务框架

原文链接:https://www.cnblogs.com/wmproxy/p/17983815/wmproxy44

体验地址:http://www.jnpfsoft.com/?from=001

用户头像

还未添加个人签名 2023-06-19 加入

还未添加个人简介

评论

发布
暂无评论
从零开始用Rust编写nginx,命令行参数的设计与解析及说明_nginx_不在线第一只蜗牛_InfoQ写作社区