github.com/Uhtred009/v2ray-core-1@v4.31.2+incompatible/infra/control/fetch.go (about) 1 package control 2 3 import ( 4 "net/http" 5 "net/url" 6 "os" 7 "strings" 8 "time" 9 10 "v2ray.com/core/common" 11 "v2ray.com/core/common/buf" 12 ) 13 14 type FetchCommand struct{} 15 16 func (c *FetchCommand) Name() string { 17 return "fetch" 18 } 19 20 func (c *FetchCommand) Description() Description { 21 return Description{ 22 Short: "Fetch resources", 23 Usage: []string{"v2ctl fetch <url>"}, 24 } 25 } 26 27 func (c *FetchCommand) Execute(args []string) error { 28 if len(args) < 1 { 29 return newError("empty url") 30 } 31 content, err := FetchHTTPContent(args[0]) 32 if err != nil { 33 return newError("failed to read HTTP response").Base(err) 34 } 35 36 os.Stdout.Write(content) 37 return nil 38 } 39 40 // FetchHTTPContent dials https for remote content 41 func FetchHTTPContent(target string) ([]byte, error) { 42 43 parsedTarget, err := url.Parse(target) 44 if err != nil { 45 return nil, newError("invalid URL: ", target).Base(err) 46 } 47 48 if s := strings.ToLower(parsedTarget.Scheme); s != "http" && s != "https" { 49 return nil, newError("invalid scheme: ", parsedTarget.Scheme) 50 } 51 52 client := &http.Client{ 53 Timeout: 30 * time.Second, 54 } 55 resp, err := client.Do(&http.Request{ 56 Method: "GET", 57 URL: parsedTarget, 58 Close: true, 59 }) 60 if err != nil { 61 return nil, newError("failed to dial to ", target).Base(err) 62 } 63 defer resp.Body.Close() 64 65 if resp.StatusCode != 200 { 66 return nil, newError("unexpected HTTP status code: ", resp.StatusCode) 67 } 68 69 content, err := buf.ReadAllToBytes(resp.Body) 70 if err != nil { 71 return nil, newError("failed to read HTTP response").Base(err) 72 } 73 74 return content, nil 75 } 76 77 func init() { 78 common.Must(RegisterCommand(&FetchCommand{})) 79 }