github.com/v2fly/v2ray-core/v4@v4.45.2/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  	"github.com/v2fly/v2ray-core/v4/common"
    11  	"github.com/v2fly/v2ray-core/v4/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  	parsedTarget, err := url.Parse(target)
    43  	if err != nil {
    44  		return nil, newError("invalid URL: ", target).Base(err)
    45  	}
    46  
    47  	if s := strings.ToLower(parsedTarget.Scheme); s != "http" && s != "https" {
    48  		return nil, newError("invalid scheme: ", parsedTarget.Scheme)
    49  	}
    50  
    51  	client := &http.Client{
    52  		Timeout: 30 * time.Second,
    53  	}
    54  	resp, err := client.Do(&http.Request{
    55  		Method: "GET",
    56  		URL:    parsedTarget,
    57  		Close:  true,
    58  	})
    59  	if err != nil {
    60  		return nil, newError("failed to dial to ", target).Base(err)
    61  	}
    62  	defer resp.Body.Close()
    63  
    64  	if resp.StatusCode != 200 {
    65  		return nil, newError("unexpected HTTP status code: ", resp.StatusCode)
    66  	}
    67  
    68  	content, err := buf.ReadAllToBytes(resp.Body)
    69  	if err != nil {
    70  		return nil, newError("failed to read HTTP response").Base(err)
    71  	}
    72  
    73  	return content, nil
    74  }
    75  
    76  func init() {
    77  	common.Must(RegisterCommand(&FetchCommand{}))
    78  }