jsonem.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. package jsonem
  2. import (
  3. "bytes"
  4. "io"
  5. "io/ioutil"
  6. "net/http"
  7. "net/url"
  8. "os"
  9. "strings"
  10. "time"
  11. "v2ray.com/core"
  12. "v2ray.com/core/common"
  13. "v2ray.com/core/common/buf"
  14. "v2ray.com/core/common/cmdarg"
  15. "v2ray.com/core/infra/conf"
  16. "v2ray.com/core/infra/conf/serial"
  17. )
  18. func init() {
  19. common.Must(core.RegisterConfigLoader(&core.ConfigFormat{
  20. Name: "JSON",
  21. Extension: []string{"json"},
  22. Loader: func(input interface{}) (*core.Config, error) {
  23. switch v := input.(type) {
  24. case cmdarg.Arg:
  25. cf := &conf.Config{}
  26. for _, arg := range v {
  27. newError("Reading config: ", arg).AtInfo().WriteToLog()
  28. r, err := LoadArg(arg)
  29. common.Must(err)
  30. c, err := serial.DecodeJSONConfig(r)
  31. common.Must(err)
  32. cf.Override(c, arg)
  33. }
  34. return cf.Build()
  35. case io.Reader:
  36. return serial.LoadJSONConfig(v)
  37. default:
  38. return nil, newError("unknow type")
  39. }
  40. },
  41. }))
  42. }
  43. func LoadArg(arg string) (out io.Reader, err error) {
  44. var data []byte
  45. if strings.HasPrefix(arg, "http://") || strings.HasPrefix(arg, "https://") {
  46. data, err = FetchHTTPContent(arg)
  47. } else if arg == "stdin:" {
  48. data, err = ioutil.ReadAll(os.Stdin)
  49. } else {
  50. data, err = ioutil.ReadFile(arg)
  51. }
  52. if err != nil {
  53. return
  54. }
  55. out = bytes.NewBuffer(data)
  56. return
  57. }
  58. func FetchHTTPContent(target string) ([]byte, error) {
  59. parsedTarget, err := url.Parse(target)
  60. if err != nil {
  61. return nil, newError("invalid URL: ", target).Base(err)
  62. }
  63. if s := strings.ToLower(parsedTarget.Scheme); s != "http" && s != "https" {
  64. return nil, newError("invalid scheme: ", parsedTarget.Scheme)
  65. }
  66. client := &http.Client{
  67. Timeout: 30 * time.Second,
  68. }
  69. resp, err := client.Do(&http.Request{
  70. Method: "GET",
  71. URL: parsedTarget,
  72. Close: true,
  73. })
  74. if err != nil {
  75. return nil, newError("failed to dial to ", target).Base(err)
  76. }
  77. defer resp.Body.Close()
  78. if resp.StatusCode != 200 {
  79. return nil, newError("unexpected HTTP status code: ", resp.StatusCode)
  80. }
  81. content, err := buf.ReadAllToBytes(resp.Body)
  82. if err != nil {
  83. return nil, newError("failed to read HTTP response").Base(err)
  84. }
  85. return content, nil
  86. }