github.com/yaling888/clash@v1.53.0/adapter/provider/parser.go (about) 1 package provider 2 3 import ( 4 "errors" 5 "fmt" 6 "time" 7 8 "github.com/yaling888/clash/adapter" 9 "github.com/yaling888/clash/common/structure" 10 C "github.com/yaling888/clash/constant" 11 types "github.com/yaling888/clash/constant/provider" 12 ) 13 14 var errVehicleType = errors.New("unsupport vehicle type") 15 16 type healthCheckSchema struct { 17 Enable bool `provider:"enable"` 18 URL string `provider:"url"` 19 Interval time.Duration `provider:"interval"` 20 Lazy bool `provider:"lazy,omitempty"` 21 } 22 23 type proxyProviderSchema struct { 24 Type string `provider:"type"` 25 Path string `provider:"path"` 26 URL string `provider:"url,omitempty"` 27 URLProxy bool `provider:"url-proxy,omitempty"` 28 Interval time.Duration `provider:"interval,omitempty"` 29 Filter string `provider:"filter,omitempty"` 30 HealthCheck healthCheckSchema `provider:"health-check,omitempty"` 31 ForceCertVerify bool `provider:"force-cert-verify,omitempty"` 32 UDP bool `provider:"udp,omitempty"` 33 DisableUDP bool `provider:"disable-udp,omitempty"` 34 DisableDNS bool `provider:"disable-dns,omitempty"` 35 RandomHost bool `provider:"rand-host,omitempty"` 36 PrefixName string `provider:"prefix-name,omitempty"` 37 Header map[string][]string `provider:"header,omitempty"` 38 } 39 40 func ParseProxyProvider(name string, mapping map[string]any, _ bool) (types.ProxyProvider, error) { 41 decoder := structure.NewDecoder(structure.Option{TagName: "provider", WeaklyTypedInput: true}) 42 43 globalForceCertVerify := true 44 schema := &proxyProviderSchema{ 45 ForceCertVerify: globalForceCertVerify, 46 HealthCheck: healthCheckSchema{ 47 Lazy: true, 48 }, 49 } 50 51 if err := decoder.Decode(mapping, schema); err != nil { 52 return nil, err 53 } 54 55 var hcInterval time.Duration 56 if schema.HealthCheck.Enable { 57 hcInterval = schema.HealthCheck.Interval 58 } 59 hc := NewHealthCheck([]C.Proxy{}, schema.HealthCheck.URL, hcInterval, schema.HealthCheck.Lazy) 60 61 vehicle, err := newVehicle(schema) 62 if err != nil { 63 return nil, err 64 } 65 66 interval := schema.Interval 67 filter := schema.Filter 68 option := adapter.ProxyOption{ 69 ForceCertVerify: schema.ForceCertVerify, 70 ForceUDP: schema.UDP, 71 DisableUDP: schema.DisableUDP, 72 DisableDNS: schema.DisableDNS, 73 RandomHost: schema.RandomHost, 74 PrefixName: schema.PrefixName, 75 AutoCipher: true, 76 } 77 return NewProxySetProvider(name, interval, filter, vehicle, hc, globalForceCertVerify, option) 78 } 79 80 func newVehicle(schema *proxyProviderSchema) (types.Vehicle, error) { 81 path := C.Path.Resolve(schema.Path) 82 83 switch schema.Type { 84 case "file": 85 return NewFileVehicle(path), nil 86 case "http": 87 if !C.Path.IsSubHomeDir(path) { 88 return nil, errors.New("the path is not a sub path of home directory") 89 } 90 91 if schema.Header == nil { 92 schema.Header = map[string][]string{ 93 "User-Agent": {"ClashPlusPro/" + C.Version}, 94 } 95 } else if _, ok := schema.Header["User-Agent"]; !ok { 96 schema.Header["User-Agent"] = []string{"ClashPlusPro/" + C.Version} 97 } 98 99 return NewHTTPVehicle(path, schema.URL, schema.URLProxy, schema.Header), nil 100 default: 101 return nil, fmt.Errorf("%w: %s", errVehicleType, schema.Type) 102 } 103 }