external.go 1.8 KB

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