http.go 1.9 KB

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