mirror of
https://github.com/e1732a364fed/v2ray_simple.git
synced 2025-12-24 13:27:56 +08:00
完成url标准格式,见docs/url.md; 修订代码
This commit is contained in:
@@ -135,7 +135,7 @@ verysimple -c server.json
|
||||
|
||||
verysimple 继承 v2simple的一个优点,就是服务端的配置也可以用url做到。谁规定url只能用于分享客户端配置了?一条url肯定比json更容易配置,不容易出错。
|
||||
|
||||
关于url格式,见: https://github.com/e1732a364fed/v2ray_simple/discussions/163
|
||||
关于url格式,见: [url标准定义](docs/url.md)
|
||||
|
||||
### 命令行模式
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ package grpc
|
||||
|
||||
import (
|
||||
"github.com/e1732a364fed/v2ray_simple/advLayer"
|
||||
"github.com/e1732a364fed/v2ray_simple/utils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -79,10 +80,10 @@ func (Creator) NewClientFromConf(conf *advLayer.Conf) (advLayer.Client, error) {
|
||||
grpc_multi := false
|
||||
if extra := conf.Extra; len(extra) > 0 {
|
||||
if thing := extra["grpc_multi"]; thing != nil {
|
||||
if use_multi, ok := thing.(bool); ok {
|
||||
grpc_multi = use_multi
|
||||
}
|
||||
|
||||
if v, ok := utils.AnyToBool(thing); ok {
|
||||
grpc_multi = v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -191,7 +191,7 @@ func getExtra(extra map[string]any) (useHysteria, hysteria_manual bool,
|
||||
maxStreamsInOneConn int64) {
|
||||
|
||||
if thing := extra["maxStreamsInOneConn"]; thing != nil {
|
||||
if count, ok := thing.(int64); ok && count > 0 {
|
||||
if count, ok := utils.AnyToInt64(thing); ok && count > 0 {
|
||||
if ce := utils.CanLogInfo("Quic max Streams In One Conn"); ce != nil {
|
||||
ce.Write(zap.Int("count,", int(count)))
|
||||
} else {
|
||||
@@ -209,7 +209,7 @@ func getExtra(extra map[string]any) (useHysteria, hysteria_manual bool,
|
||||
useHysteria = true
|
||||
|
||||
if thing := extra["mbps"]; thing != nil {
|
||||
if mbps, ok := thing.(int64); ok && mbps > 1 {
|
||||
if mbps, ok := utils.AnyToInt64(thing); ok && mbps > 1 {
|
||||
maxbyteCount = int(mbps) * 1024 * 1024 / 8
|
||||
}
|
||||
} else {
|
||||
@@ -224,7 +224,7 @@ func getExtra(extra map[string]any) (useHysteria, hysteria_manual bool,
|
||||
}
|
||||
|
||||
if thing := extra["hy_manual"]; thing != nil {
|
||||
if ismanual, ok := thing.(bool); ok {
|
||||
if ismanual, ok := utils.AnyToBool(thing); ok {
|
||||
hysteria_manual = ismanual
|
||||
if ismanual {
|
||||
|
||||
@@ -235,7 +235,7 @@ func getExtra(extra map[string]any) (useHysteria, hysteria_manual bool,
|
||||
}
|
||||
|
||||
if thing := extra["hy_manual_initial_rate"]; thing != nil {
|
||||
if initRate, ok := thing.(float64); ok {
|
||||
if initRate, ok := utils.AnyToFloat64(thing); ok {
|
||||
|
||||
if rateOk(initRate) == 0 {
|
||||
TheCustomRate = initRate
|
||||
|
||||
@@ -372,8 +372,8 @@ func interactively_hotLoadUrlConfig() {
|
||||
Select := promptui.Select{
|
||||
Label: "请选择你的url的格式类型",
|
||||
Items: []string{
|
||||
"协议官方url格式(视代理协议不同而不同)",
|
||||
"vs标准url格式",
|
||||
"协议官方url格式(视代理协议不同而不同)",
|
||||
},
|
||||
}
|
||||
i, result, err := Select.Run()
|
||||
@@ -386,16 +386,16 @@ func interactively_hotLoadUrlConfig() {
|
||||
fmt.Printf("你选择了 %s\n", result)
|
||||
|
||||
switch i {
|
||||
case 0:
|
||||
case 1:
|
||||
fmt.Printf("目前暂不支持")
|
||||
return
|
||||
|
||||
case 1:
|
||||
case 0:
|
||||
Select := promptui.Select{
|
||||
Label: "请选择该url是用于服务端还是客户端",
|
||||
Label: "请选择该url是用于dial还是listen",
|
||||
Items: []string{
|
||||
"客户端",
|
||||
"服务端",
|
||||
"dial",
|
||||
"listen",
|
||||
},
|
||||
}
|
||||
i, result, err := Select.Run()
|
||||
@@ -418,7 +418,7 @@ func interactively_hotLoadUrlConfig() {
|
||||
}
|
||||
|
||||
if i == 0 {
|
||||
u, sn, _, okTls, err := proxy.GetRealProtocolFromClientUrl(theUrlStr)
|
||||
u, sn, creator, okTls, err := proxy.GetRealProtocolFromClientUrl(theUrlStr)
|
||||
if err != nil {
|
||||
fmt.Printf("parse url failed %v\n", err)
|
||||
return
|
||||
@@ -432,12 +432,17 @@ func interactively_hotLoadUrlConfig() {
|
||||
fmt.Printf("parse url failed %v\n", err)
|
||||
return
|
||||
}
|
||||
dc, err = creator.URLToDialConf(u, dc, proxy.UrlStandardFormat)
|
||||
if err != nil {
|
||||
fmt.Printf("parse url step 2 failed %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
hotLoadDialConfForRuntime("", []*proxy.DialConf{dc})
|
||||
|
||||
} else {
|
||||
|
||||
u, sn, _, okTls, err := proxy.GetRealProtocolFromServerUrl(theUrlStr)
|
||||
u, sn, creator, okTls, err := proxy.GetRealProtocolFromServerUrl(theUrlStr)
|
||||
if err != nil {
|
||||
fmt.Printf("parse url failed %v\n", err)
|
||||
return
|
||||
@@ -453,7 +458,11 @@ func interactively_hotLoadUrlConfig() {
|
||||
fmt.Printf("parse url failed %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
lc, err = creator.URLToListenConf(u, lc, proxy.UrlStandardFormat)
|
||||
if err != nil {
|
||||
fmt.Printf("parse url step 2 failed %v\n", err)
|
||||
return
|
||||
}
|
||||
hotLoadListenConfForRuntime([]*proxy.ListenConf{lc})
|
||||
}
|
||||
return
|
||||
|
||||
@@ -5,6 +5,8 @@ package configAdapter provides methods to convert proxy.ListenConf and proxy.Dia
|
||||
|
||||
参考 https://github.com/e1732a364fed/v2ray_simple/discussions/163
|
||||
|
||||
以及 docs/url.md
|
||||
|
||||
本包内的函数不支持 vs约定的 末尾+s即表示使用tls的用法, 所以调用函数之前要预处理一下。
|
||||
|
||||
本包依然秉持KISS原则,用最笨的代码、最少的依赖,实现最小的可执行文件大小以及最快的执行速度。
|
||||
|
||||
66
docs/url.md
66
docs/url.md
@@ -1,8 +1,6 @@
|
||||
|
||||
# vs的通用url格式 ( verysimple Standard URL Format )
|
||||
|
||||
虽然verysimple通用url格式从一开始就存在,但是却没有文档详细描述(阅读proxy/creator_url.go 可以了解,毕竟golang的理念是代码就是文档。)。那么在这里就作为文档进行介绍。
|
||||
|
||||
vs的通用url格式,并不遵循现存市面上的其他格式,而是针对vs的架构逻辑所设计的新格式。如果你是一个vs老手,则使用vs的通用url格式你会感觉得心应手。
|
||||
|
||||
注意,要想读懂本文档,需要了解url的基础知识。
|
||||
@@ -20,8 +18,19 @@ authority = [userinfo "@"] host [":" port]
|
||||
|
||||
```
|
||||
|
||||
举例:
|
||||
`vlesss://a684455c-b14f-11ea-bf0d-42010aaa0003@127.0.0.1:4433?insecure=true&v=0&utls=true#myvless1`
|
||||
## 举例
|
||||
|
||||
```
|
||||
vlesss://a684455c-b14f-11ea-bf0d-42010aaa0003@127.0.0.1:4433?insecure=true&v=0&utls=true#my_vless1
|
||||
|
||||
vlesss://a684455c-b14f-11ea-bf0d-42010aaa0003@127.0.0.1:4433?adv=quic&v=0&extra.maxStreamsInOneConn=6&extra.congestion_control=hy&extra.mbps=1024#my_vless_quic
|
||||
|
||||
dokodemo://?target.ip=1.1.1.1&target.port=80#my_doko
|
||||
|
||||
shadowsocks://aes-128-gcm:mypasswordxxxxx@127.0.0.1:8000#my_ss
|
||||
|
||||
socks5://myusername:mypassword@127.0.0.1:1080#my_socks5
|
||||
```
|
||||
|
||||
## 基础部分
|
||||
|
||||
@@ -37,7 +46,7 @@ authority = [userinfo "@"] host [":" port]
|
||||
|
||||
熟悉ssh的同学会看出差别,ssh中,userinfo 是不包含密码的,也就是说ssh 需要 额外参数 或 步骤 来输入密码 或 等价信息 才能进行鉴权,而我们这里直接将鉴权的信息也包含在userinfo中来。
|
||||
|
||||
在vless/vmess中 就是 uuid,在socks5/http中 就是 “用户名+密码”,在ss/trojan中就是 密码。
|
||||
在vless/vmess中 就是 uuid, 在socks5/http中, 使用 “用户名:密码”的形式, 在shadowsocks中, 使用 method:password 的形式, 在trojan 中就是 密码。
|
||||
|
||||
### host:port
|
||||
|
||||
@@ -51,7 +60,7 @@ authority = [userinfo "@"] host [":" port]
|
||||
|
||||
## query
|
||||
|
||||
v=0, 控制该proxy协议的 版本。
|
||||
v, 控制该proxy协议的 版本。
|
||||
|
||||
fallback=:80 设置回落的地址。
|
||||
|
||||
@@ -59,11 +68,46 @@ network 设置 使用的传输层,如 network="udp", 如不给出,则默认n
|
||||
|
||||
fullcone=true设置 是否需要udp的fullcone功能。
|
||||
|
||||
security=aes-128-gcm 设置 vmess/ss等存在多种加密方式等proxy的 具体加密方式
|
||||
security=aes-128-gcm 设置 vmess/ss等存在多种加密方式等proxy的 具体加密方式
|
||||
|
||||
adv=ws 设置使用的高级层,如不给出则没有高级层,如给出,可选 ws, grpc, quic
|
||||
|
||||
mux=true 是否使用内层smux
|
||||
path=/mypath 设置 http头存在时,或者用 ws的 路径 或 grpc的 service name。
|
||||
|
||||
### http 头相关
|
||||
|
||||
http=true 设置是否使用http头
|
||||
|
||||
http.method=GET 设置 http的method
|
||||
|
||||
http.version=1.1 设置http的版本
|
||||
|
||||
以 "header." 开头的字段:开头字母大写后,放到Header里。
|
||||
|
||||
比如,如果 vmess://uuid?http=true&header.host=myhost.com&header.Accept-Encoding=gzip,deflate
|
||||
|
||||
则会设置http头的header 的 Host 字段为 myhost.com,设置 Accept-Encoding 为 gzip,deflate, 如果有空格等情况的话,需要进行 百分号转译。
|
||||
|
||||
转译可以使用这个工具测试: https://www.url-encode-decode.com/
|
||||
|
||||
### extra 相关
|
||||
|
||||
在标准toml配置中,有时会填充extra项来配置额外参数。在本标准url格式中,该类配置也是相当简单的。
|
||||
|
||||
就是用 extra.yyy=zzz 的格式
|
||||
|
||||
举几个例子,比如 reject 类型的proxy 需要一个 type 的extra参数 来指示 使用什么类型的拒绝响应;
|
||||
此时在url中,这么写: extra.type=nginx
|
||||
|
||||
再举几个例子
|
||||
|
||||
```
|
||||
#quic
|
||||
extra.maxStreamsInOneConn=6&extra.congestion_control=hy&extra.mbps=1024
|
||||
|
||||
#grpc (非grpcSimple的情况)
|
||||
extra.grpc_multi=true
|
||||
```
|
||||
|
||||
### tls相关 (proxy/tlsConfig.go)
|
||||
|
||||
@@ -75,8 +119,8 @@ cert=cert.pem&key=cert.key
|
||||
|
||||
用于设置证书名称。
|
||||
|
||||
|
||||
|
||||
|
||||
### 其他
|
||||
|
||||
dokodemo的目标这么写: `target.ip=1.1.1.1&target.port=80`
|
||||
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ const (
|
||||
var (
|
||||
// Url格式 设置以何种方式解析 命令行模式/极简模式 中出现的url配置
|
||||
//
|
||||
//关于url格式的详细, 见 https://github.com/e1732a364fed/v2ray_simple/discussions/163
|
||||
//关于url格式的详细, 见 docs/url.md
|
||||
UrlFormat = UrlStandardFormat
|
||||
)
|
||||
|
||||
@@ -175,6 +175,8 @@ func URLToCommonConf(u *url.URL, conf *CommonConf) error {
|
||||
|
||||
conf.Network = q.Get("network")
|
||||
|
||||
conf.Uuid = u.User.Username()
|
||||
|
||||
conf.Fullcone = utils.QueryPositive(q, "fullcone")
|
||||
conf.Tag = u.Fragment
|
||||
conf.Path = u.Path
|
||||
@@ -281,5 +283,19 @@ func URLToListenConf(u *url.URL, conf *ListenConf) error {
|
||||
conf.TLSKey = keyFile
|
||||
}
|
||||
|
||||
targetStr := q.Get("target.ip")
|
||||
|
||||
if targetStr != "" {
|
||||
target_portStr := q.Get("target.port")
|
||||
if target_portStr != "" {
|
||||
if conf.Network == "" {
|
||||
conf.Network = "tcp"
|
||||
}
|
||||
taStr := conf.Network + "://" + targetStr + ":" + target_portStr
|
||||
conf.TargetAddr = taStr
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return e
|
||||
}
|
||||
|
||||
@@ -53,7 +53,6 @@ func init() {
|
||||
|
||||
type ServerCreator struct{}
|
||||
|
||||
// 用如下参数形式: network=tcp&target=127.0.0.1&target_port=80
|
||||
func (ServerCreator) URLToListenConf(url *url.URL, lc *proxy.ListenConf, format int) (*proxy.ListenConf, error) {
|
||||
if format != proxy.StandardMode {
|
||||
return lc, utils.ErrUnImplemented
|
||||
@@ -62,20 +61,6 @@ func (ServerCreator) URLToListenConf(url *url.URL, lc *proxy.ListenConf, format
|
||||
return nil, utils.ErrNilParameter
|
||||
}
|
||||
|
||||
targetStr := url.Query().Get("target")
|
||||
if targetStr == "" {
|
||||
return nil, utils.ErrNilParameter
|
||||
}
|
||||
|
||||
target_portStr := url.Query().Get("target_port")
|
||||
if target_portStr == "" {
|
||||
return nil, utils.ErrNilParameter
|
||||
}
|
||||
if lc.Network == "" {
|
||||
lc.Network = "tcp"
|
||||
}
|
||||
taStr := lc.Network + "://" + targetStr + ":" + target_portStr
|
||||
lc.TargetAddr = taStr
|
||||
return lc, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -57,13 +57,16 @@ func (ServerCreator) URLToListenConf(u *url.URL, lc *proxy.ListenConf, format in
|
||||
lc = &proxy.ListenConf{}
|
||||
}
|
||||
|
||||
user := u.Query().Get("user")
|
||||
pass := u.Query().Get("pass")
|
||||
if p, set := u.User.Password(); set {
|
||||
|
||||
user := u.User.Username()
|
||||
pass := p
|
||||
lc.Users = append(lc.Users, utils.UserConf{
|
||||
User: user,
|
||||
Pass: pass,
|
||||
})
|
||||
}
|
||||
|
||||
lc.Users = append(lc.Users, utils.UserConf{
|
||||
User: user,
|
||||
Pass: pass,
|
||||
})
|
||||
return lc, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -66,29 +66,11 @@ func (RejectCreator) NewClient(dc *DialConf) (Client, error) {
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func (RejectCreator) initCommonConfByURL(url *url.URL, lc *CommonConf, format int) {
|
||||
|
||||
if format != UrlStandardFormat {
|
||||
return
|
||||
}
|
||||
|
||||
nStr := url.Query().Get("type")
|
||||
|
||||
if nStr != "" {
|
||||
|
||||
lc.Extra = make(map[string]any)
|
||||
lc.Extra["type"] = nStr
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (rc RejectCreator) URLToDialConf(url *url.URL, iv *DialConf, format int) (*DialConf, error) {
|
||||
if iv == nil {
|
||||
iv = &DialConf{}
|
||||
|
||||
}
|
||||
rc.initCommonConfByURL(url, &iv.CommonConf, format)
|
||||
|
||||
return iv, nil
|
||||
}
|
||||
@@ -97,7 +79,6 @@ func (rc RejectCreator) URLToListenConf(url *url.URL, iv *ListenConf, format int
|
||||
if iv == nil {
|
||||
iv = &ListenConf{}
|
||||
}
|
||||
rc.initCommonConfByURL(url, &iv.CommonConf, format)
|
||||
|
||||
return iv, nil
|
||||
}
|
||||
|
||||
@@ -25,10 +25,11 @@ func (ClientCreator) URLToDialConf(u *url.URL, dc *proxy.DialConf, format int) (
|
||||
dc = &proxy.DialConf{}
|
||||
}
|
||||
|
||||
m := u.Query().Get("method")
|
||||
p := u.Query().Get("pass")
|
||||
if p, set := u.User.Password(); set {
|
||||
|
||||
dc.Uuid = "method:" + u.User.Username() + "\npass:" + p
|
||||
}
|
||||
|
||||
dc.Uuid = "method:" + m + "\npass:" + p
|
||||
return dc, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -38,10 +38,10 @@ func (ServerCreator) URLToListenConf(u *url.URL, lc *proxy.ListenConf, format in
|
||||
lc = &proxy.ListenConf{}
|
||||
}
|
||||
|
||||
m := u.Query().Get("method")
|
||||
p := u.Query().Get("pass")
|
||||
if p, set := u.User.Password(); set {
|
||||
lc.Uuid = "method:" + u.User.Username() + "\npass:" + p
|
||||
}
|
||||
|
||||
lc.Uuid = "method:" + m + "\npass:" + p
|
||||
return lc, nil
|
||||
|
||||
}
|
||||
|
||||
@@ -25,10 +25,10 @@ func (ClientCreator) URLToDialConf(u *url.URL, dc *proxy.DialConf, format int) (
|
||||
dc = &proxy.DialConf{}
|
||||
}
|
||||
|
||||
user := u.Query().Get("user")
|
||||
pass := u.Query().Get("pass")
|
||||
if p, set := u.User.Password(); set {
|
||||
dc.Uuid = "user:" + u.User.Username() + "\npass:" + p
|
||||
}
|
||||
|
||||
dc.Uuid = "user:" + user + "\npass:" + pass
|
||||
return dc, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -50,13 +50,15 @@ func (ServerCreator) URLToListenConf(u *url.URL, lc *proxy.ListenConf, format in
|
||||
lc = &proxy.ListenConf{}
|
||||
}
|
||||
|
||||
user := u.Query().Get("user")
|
||||
pass := u.Query().Get("pass")
|
||||
if p, set := u.User.Password(); set {
|
||||
user := u.User.Username()
|
||||
pass := p
|
||||
lc.Users = append(lc.Users, utils.UserConf{
|
||||
User: user,
|
||||
Pass: pass,
|
||||
})
|
||||
}
|
||||
|
||||
lc.Users = append(lc.Users, utils.UserConf{
|
||||
User: user,
|
||||
Pass: pass,
|
||||
})
|
||||
return lc, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -25,9 +25,10 @@ func (ClientCreator) URLToDialConf(url *url.URL, dc *proxy.DialConf, format int)
|
||||
case proxy.UrlStandardFormat:
|
||||
if dc == nil {
|
||||
dc = &proxy.DialConf{}
|
||||
uuidStr := url.User.Username()
|
||||
dc.Uuid = uuidStr
|
||||
|
||||
}
|
||||
uuidStr := url.User.Username()
|
||||
dc.Uuid = uuidStr
|
||||
return dc, nil
|
||||
default:
|
||||
return nil, utils.ErrUnImplemented
|
||||
|
||||
@@ -35,11 +35,10 @@ func (ServerCreator) URLToListenConf(url *url.URL, lc *proxy.ListenConf, format
|
||||
case proxy.UrlStandardFormat:
|
||||
if lc == nil {
|
||||
lc = &proxy.ListenConf{}
|
||||
|
||||
uuidStr := url.User.Username()
|
||||
lc.Uuid = uuidStr
|
||||
}
|
||||
|
||||
uuidStr := url.User.Username()
|
||||
lc.Uuid = uuidStr
|
||||
return lc, nil
|
||||
default:
|
||||
return nil, utils.ErrUnImplemented
|
||||
|
||||
@@ -59,27 +59,8 @@ func (ClientCreator) URLToDialConf(url *url.URL, dc *proxy.DialConf, format int)
|
||||
case proxy.UrlStandardFormat:
|
||||
if dc == nil {
|
||||
dc = &proxy.DialConf{}
|
||||
}
|
||||
uuidStr := url.User.Username()
|
||||
dc.Uuid = uuidStr
|
||||
|
||||
vStr := url.Query().Get("v")
|
||||
if vStr != "" {
|
||||
v, e := strconv.Atoi(vStr)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
dc.Version = v
|
||||
if v == 1 {
|
||||
vless1_udp_multiStr := url.Query().Get("vless1_udp_multi")
|
||||
if vless1_udp_multiStr == "true" || vless1_udp_multiStr == "1" {
|
||||
if dc.Extra == nil {
|
||||
dc.Extra = make(map[string]any)
|
||||
}
|
||||
dc.Extra["vless1_udp_multi"] = true
|
||||
|
||||
}
|
||||
}
|
||||
uuidStr := url.User.Username()
|
||||
dc.Uuid = uuidStr
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"io"
|
||||
"net"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"unsafe"
|
||||
|
||||
"github.com/e1732a364fed/v2ray_simple/netLayer"
|
||||
@@ -54,18 +53,8 @@ func (ServerCreator) URLToListenConf(url *url.URL, lc *proxy.ListenConf, format
|
||||
if lc == nil {
|
||||
lc = &proxy.ListenConf{}
|
||||
|
||||
}
|
||||
|
||||
uuidStr := url.User.Username()
|
||||
lc.Uuid = uuidStr
|
||||
vStr := url.Query().Get("v")
|
||||
if vStr != "" {
|
||||
v, e := strconv.Atoi(vStr)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
lc.Version = v
|
||||
|
||||
uuidStr := url.User.Username()
|
||||
lc.Uuid = uuidStr
|
||||
}
|
||||
|
||||
return lc, nil
|
||||
|
||||
@@ -56,23 +56,12 @@ func (ClientCreator) URLToDialConf(url *url.URL, dc *proxy.DialConf, format int)
|
||||
|
||||
if dc == nil {
|
||||
dc = &proxy.DialConf{}
|
||||
}
|
||||
uuidStr := url.User.Username()
|
||||
|
||||
uuidStr := url.User.Username()
|
||||
|
||||
dc.Uuid = uuidStr
|
||||
|
||||
query := url.Query()
|
||||
|
||||
security := query.Get("security")
|
||||
if security != "" {
|
||||
if dc.Extra == nil {
|
||||
dc.Extra = make(map[string]any)
|
||||
}
|
||||
|
||||
dc.Extra[Security_confStr] = security
|
||||
dc.Uuid = uuidStr
|
||||
|
||||
}
|
||||
|
||||
return dc, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -76,11 +76,10 @@ func (ServerCreator) URLToListenConf(url *url.URL, lc *proxy.ListenConf, format
|
||||
if lc == nil {
|
||||
lc = &proxy.ListenConf{}
|
||||
|
||||
uuidStr := url.User.Username()
|
||||
lc.Uuid = uuidStr
|
||||
}
|
||||
|
||||
uuidStr := url.User.Username()
|
||||
lc.Uuid = uuidStr
|
||||
|
||||
return lc, nil
|
||||
default:
|
||||
return lc, utils.ErrUnImplemented
|
||||
|
||||
133
utils/cast.go
Normal file
133
utils/cast.go
Normal file
@@ -0,0 +1,133 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func StrPositive(value string) bool {
|
||||
value = strings.ToLower(value)
|
||||
return value == "1" || value == "on" || value == "true"
|
||||
}
|
||||
func StrNegative(value string) bool {
|
||||
value = strings.ToLower(value)
|
||||
|
||||
return value == "" || value == "0" || value == "off" || value == "false"
|
||||
}
|
||||
|
||||
func QueryPositive(query url.Values, key string) bool {
|
||||
nStr := query.Get(key)
|
||||
return StrPositive(nStr)
|
||||
}
|
||||
|
||||
func QueryNegative(query url.Values, key string) bool {
|
||||
nStr := query.Get(key)
|
||||
return StrNegative(nStr)
|
||||
}
|
||||
|
||||
func AnyToBool(a any) (v bool, ok bool) {
|
||||
ok = true
|
||||
switch value := a.(type) {
|
||||
case bool:
|
||||
v = value
|
||||
case int:
|
||||
if value == 0 {
|
||||
v = false
|
||||
} else {
|
||||
v = true
|
||||
}
|
||||
case int64:
|
||||
if value == 0 {
|
||||
v = false
|
||||
} else {
|
||||
v = true
|
||||
}
|
||||
case string:
|
||||
if StrNegative(value) {
|
||||
v = false
|
||||
} else if StrPositive(value) {
|
||||
v = true
|
||||
}
|
||||
default:
|
||||
var i64 int64
|
||||
i64, ok = AnyToInt64(a)
|
||||
if ok {
|
||||
v, ok = AnyToBool(i64)
|
||||
return
|
||||
}
|
||||
ok = false
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func AnyToInt64(a any) (int64, bool) {
|
||||
switch value := a.(type) {
|
||||
case int64:
|
||||
return value, true
|
||||
case int:
|
||||
return int64(value), true
|
||||
case uint:
|
||||
return int64(value), true
|
||||
case int32:
|
||||
return int64(value), true
|
||||
case int16:
|
||||
return int64(value), true
|
||||
case int8:
|
||||
return int64(value), true
|
||||
case uint64:
|
||||
return int64(value), true
|
||||
case uint32:
|
||||
return int64(value), true
|
||||
case uint16:
|
||||
return int64(value), true
|
||||
case uint8:
|
||||
return int64(value), true
|
||||
case float64:
|
||||
return int64(value), true
|
||||
case float32:
|
||||
return int64(value), true
|
||||
case string:
|
||||
v, err := strconv.Atoi(value)
|
||||
if err == nil {
|
||||
return int64(v), true
|
||||
}
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
||||
func AnyToFloat64(a any) (float64, bool) {
|
||||
switch value := a.(type) {
|
||||
case float64:
|
||||
return value, true
|
||||
case float32:
|
||||
return float64(value), true
|
||||
|
||||
case int64:
|
||||
return float64(value), true
|
||||
case int:
|
||||
return float64(value), true
|
||||
case uint:
|
||||
return float64(value), true
|
||||
case int32:
|
||||
return float64(value), true
|
||||
case int16:
|
||||
return float64(value), true
|
||||
case int8:
|
||||
return float64(value), true
|
||||
case uint32:
|
||||
return float64(value), true
|
||||
case uint16:
|
||||
return float64(value), true
|
||||
case uint8:
|
||||
return float64(value), true
|
||||
case string:
|
||||
v, err := strconv.ParseFloat(value, 64)
|
||||
if err == nil {
|
||||
return v, true
|
||||
}
|
||||
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
@@ -3,7 +3,6 @@ package utils
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
@@ -86,13 +85,3 @@ func WrapFuncForPromptUI(f func(string) bool) func(string) error {
|
||||
return ErrInvalidData
|
||||
}
|
||||
}
|
||||
|
||||
func QueryPositive(query url.Values, key string) bool {
|
||||
nStr := query.Get(key)
|
||||
return nStr == "true" || nStr == "1"
|
||||
}
|
||||
|
||||
func QueryNegative(query url.Values, key string) bool {
|
||||
nStr := query.Get(key)
|
||||
return nStr == "false" || nStr == "0"
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ GenerateUUID_v4 生成符合v4标准的uuid.
|
||||
|
||||
version: https://datatracker.ietf.org/doc/html/rfc4122#section-4.1.3
|
||||
*/
|
||||
func GenerateUUID_v4() (r [UUID_BytesLen]byte) {
|
||||
func GenerateUUID_v4() (r UUID) {
|
||||
rand.Reader.Read(r[:])
|
||||
r[6] = (r[6] & 0x0f) | 0x40 // Version 4
|
||||
r[8] = (r[8] & 0x3f) | 0x80
|
||||
|
||||
Reference in New Issue
Block a user