github.com/metacubex/mihomo@v1.18.5/adapter/provider/parser.go (about) 1 package provider 2 3 import ( 4 "errors" 5 "fmt" 6 "time" 7 8 "github.com/metacubex/mihomo/common/structure" 9 "github.com/metacubex/mihomo/common/utils" 10 "github.com/metacubex/mihomo/component/resource" 11 C "github.com/metacubex/mihomo/constant" 12 "github.com/metacubex/mihomo/constant/features" 13 types "github.com/metacubex/mihomo/constant/provider" 14 ) 15 16 var ( 17 errVehicleType = errors.New("unsupport vehicle type") 18 errSubPath = errors.New("path is not subpath of home directory") 19 ) 20 21 type healthCheckSchema struct { 22 Enable bool `provider:"enable"` 23 URL string `provider:"url"` 24 Interval int `provider:"interval"` 25 TestTimeout int `provider:"timeout,omitempty"` 26 Lazy bool `provider:"lazy,omitempty"` 27 ExpectedStatus string `provider:"expected-status,omitempty"` 28 } 29 30 type OverrideSchema struct { 31 UDP *bool `provider:"udp,omitempty"` 32 Up *string `provider:"up,omitempty"` 33 Down *string `provider:"down,omitempty"` 34 DialerProxy *string `provider:"dialer-proxy,omitempty"` 35 SkipCertVerify *bool `provider:"skip-cert-verify,omitempty"` 36 Interface *string `provider:"interface-name,omitempty"` 37 RoutingMark *int `provider:"routing-mark,omitempty"` 38 IPVersion *string `provider:"ip-version,omitempty"` 39 AdditionalPrefix *string `provider:"additional-prefix,omitempty"` 40 AdditionalSuffix *string `provider:"additional-suffix,omitempty"` 41 } 42 43 type proxyProviderSchema struct { 44 Type string `provider:"type"` 45 Path string `provider:"path,omitempty"` 46 URL string `provider:"url,omitempty"` 47 Proxy string `provider:"proxy,omitempty"` 48 Interval int `provider:"interval,omitempty"` 49 Filter string `provider:"filter,omitempty"` 50 ExcludeFilter string `provider:"exclude-filter,omitempty"` 51 ExcludeType string `provider:"exclude-type,omitempty"` 52 DialerProxy string `provider:"dialer-proxy,omitempty"` 53 54 HealthCheck healthCheckSchema `provider:"health-check,omitempty"` 55 Override OverrideSchema `provider:"override,omitempty"` 56 Header map[string][]string `provider:"header,omitempty"` 57 } 58 59 func ParseProxyProvider(name string, mapping map[string]any) (types.ProxyProvider, error) { 60 decoder := structure.NewDecoder(structure.Option{TagName: "provider", WeaklyTypedInput: true}) 61 62 schema := &proxyProviderSchema{ 63 HealthCheck: healthCheckSchema{ 64 Lazy: true, 65 }, 66 } 67 if err := decoder.Decode(mapping, schema); err != nil { 68 return nil, err 69 } 70 71 expectedStatus, err := utils.NewUnsignedRanges[uint16](schema.HealthCheck.ExpectedStatus) 72 if err != nil { 73 return nil, err 74 } 75 76 var hcInterval uint 77 if schema.HealthCheck.Enable { 78 if schema.HealthCheck.Interval == 0 { 79 schema.HealthCheck.Interval = 300 80 } 81 hcInterval = uint(schema.HealthCheck.Interval) 82 } 83 hc := NewHealthCheck([]C.Proxy{}, schema.HealthCheck.URL, uint(schema.HealthCheck.TestTimeout), hcInterval, schema.HealthCheck.Lazy, expectedStatus) 84 85 var vehicle types.Vehicle 86 switch schema.Type { 87 case "file": 88 path := C.Path.Resolve(schema.Path) 89 vehicle = resource.NewFileVehicle(path) 90 case "http": 91 path := C.Path.GetPathByHash("proxies", schema.URL) 92 if schema.Path != "" { 93 path = C.Path.Resolve(schema.Path) 94 if !features.CMFA && !C.Path.IsSafePath(path) { 95 return nil, fmt.Errorf("%w: %s", errSubPath, path) 96 } 97 } 98 vehicle = resource.NewHTTPVehicle(schema.URL, path, schema.Proxy, schema.Header) 99 default: 100 return nil, fmt.Errorf("%w: %s", errVehicleType, schema.Type) 101 } 102 103 interval := time.Duration(uint(schema.Interval)) * time.Second 104 filter := schema.Filter 105 excludeFilter := schema.ExcludeFilter 106 excludeType := schema.ExcludeType 107 dialerProxy := schema.DialerProxy 108 override := schema.Override 109 110 return NewProxySetProvider(name, interval, filter, excludeFilter, excludeType, dialerProxy, override, vehicle, hc) 111 }