github.com/v2fly/v2ray-core/v5@v5.16.2-0.20240507031116-8191faa6e095/app/subscription/documentfetcher/httpfetcher/http.go (about)

     1  package httpfetcher
     2  
     3  import (
     4  	"context"
     5  	"io"
     6  	gonet "net"
     7  	"net/http"
     8  
     9  	"github.com/v2fly/v2ray-core/v5/common"
    10  	"github.com/v2fly/v2ray-core/v5/common/net"
    11  
    12  	"github.com/v2fly/v2ray-core/v5/app/subscription"
    13  	"github.com/v2fly/v2ray-core/v5/app/subscription/documentfetcher"
    14  	"github.com/v2fly/v2ray-core/v5/common/environment"
    15  	"github.com/v2fly/v2ray-core/v5/common/environment/envctx"
    16  )
    17  
    18  //go:generate go run github.com/v2fly/v2ray-core/v5/common/errors/errorgen
    19  
    20  func newHTTPFetcher() *httpFetcher {
    21  	return &httpFetcher{}
    22  }
    23  
    24  func init() {
    25  	common.Must(documentfetcher.RegisterFetcher("http", newHTTPFetcher()))
    26  }
    27  
    28  type httpFetcher struct{}
    29  
    30  func (h *httpFetcher) DownloadDocument(ctx context.Context, source *subscription.ImportSource, opts ...documentfetcher.FetcherOptions) ([]byte, error) {
    31  	instanceNetwork := envctx.EnvironmentFromContext(ctx).(environment.InstanceNetworkCapabilitySet)
    32  	outboundDialer := instanceNetwork.OutboundDialer()
    33  	var httpRoundTripper http.RoundTripper //nolint: gosimple
    34  	httpRoundTripper = &http.Transport{
    35  		DialContext: func(ctx_ context.Context, network string, addr string) (gonet.Conn, error) {
    36  			dest, err := net.ParseDestination(network + ":" + addr)
    37  			if err != nil {
    38  				return nil, newError("unable to parse destination")
    39  			}
    40  			return outboundDialer(ctx, dest, source.ImportUsingTag)
    41  		},
    42  	}
    43  	request, err := http.NewRequest("GET", source.Url, nil)
    44  	if err != nil {
    45  		return nil, newError("unable to generate request").Base(err)
    46  	}
    47  	resp, err := httpRoundTripper.RoundTrip(request)
    48  	if err != nil {
    49  		return nil, newError("unable to send request").Base(err)
    50  	}
    51  	defer resp.Body.Close()
    52  	if resp.StatusCode != http.StatusOK {
    53  		return nil, newError("unexpected http status ", resp.StatusCode, "=", resp.Status)
    54  	}
    55  	data, err := io.ReadAll(resp.Body)
    56  	if err != nil {
    57  		return nil, newError("unable to read response").Base(err)
    58  	}
    59  	return data, nil
    60  }