github.com/xtls/xray-core@v1.8.12-0.20240518155711-3168d27b0bdb/main/confloader/external/external.go (about) 1 package external 2 3 //go:generate go run github.com/xtls/xray-core/common/errors/errorgen 4 5 import ( 6 "bytes" 7 "io" 8 "net/http" 9 "net/url" 10 "os" 11 "strings" 12 "time" 13 14 "github.com/xtls/xray-core/common/buf" 15 "github.com/xtls/xray-core/common/platform/ctlcmd" 16 "github.com/xtls/xray-core/main/confloader" 17 ) 18 19 func ConfigLoader(arg string) (out io.Reader, err error) { 20 var data []byte 21 switch { 22 case strings.HasPrefix(arg, "http://"), strings.HasPrefix(arg, "https://"): 23 data, err = FetchHTTPContent(arg) 24 25 case arg == "stdin:": 26 data, err = io.ReadAll(os.Stdin) 27 28 default: 29 data, err = os.ReadFile(arg) 30 } 31 32 if err != nil { 33 return 34 } 35 out = bytes.NewBuffer(data) 36 return 37 } 38 39 func FetchHTTPContent(target string) ([]byte, error) { 40 parsedTarget, err := url.Parse(target) 41 if err != nil { 42 return nil, newError("invalid URL: ", target).Base(err) 43 } 44 45 if s := strings.ToLower(parsedTarget.Scheme); s != "http" && s != "https" { 46 return nil, newError("invalid scheme: ", parsedTarget.Scheme) 47 } 48 49 client := &http.Client{ 50 Timeout: 30 * time.Second, 51 } 52 resp, err := client.Do(&http.Request{ 53 Method: "GET", 54 URL: parsedTarget, 55 Close: true, 56 }) 57 if err != nil { 58 return nil, newError("failed to dial to ", target).Base(err) 59 } 60 defer resp.Body.Close() 61 62 if resp.StatusCode != 200 { 63 return nil, newError("unexpected HTTP status code: ", resp.StatusCode) 64 } 65 66 content, err := buf.ReadAllToBytes(resp.Body) 67 if err != nil { 68 return nil, newError("failed to read HTTP response").Base(err) 69 } 70 71 return content, nil 72 } 73 74 func ExtConfigLoader(files []string, reader io.Reader) (io.Reader, error) { 75 buf, err := ctlcmd.Run(append([]string{"convert"}, files...), reader) 76 if err != nil { 77 return nil, err 78 } 79 80 return strings.NewReader(buf.String()), nil 81 } 82 83 func init() { 84 confloader.EffectiveConfigFileLoader = ConfigLoader 85 confloader.EffectiveExtConfigLoader = ExtConfigLoader 86 }