github.com/igoogolx/clash@v1.19.8/adapter/provider/vehicle.go (about)

     1  package provider
     2  
     3  import (
     4  	"context"
     5  	"io"
     6  	"net"
     7  	"net/http"
     8  	"net/url"
     9  	"os"
    10  	"time"
    11  
    12  	"github.com/igoogolx/clash/component/dialer"
    13  	types "github.com/igoogolx/clash/constant/provider"
    14  )
    15  
    16  type FileVehicle struct {
    17  	path string
    18  }
    19  
    20  func (f *FileVehicle) Type() types.VehicleType {
    21  	return types.File
    22  }
    23  
    24  func (f *FileVehicle) Path() string {
    25  	return f.path
    26  }
    27  
    28  func (f *FileVehicle) Read() ([]byte, error) {
    29  	return os.ReadFile(f.path)
    30  }
    31  
    32  func NewFileVehicle(path string) *FileVehicle {
    33  	return &FileVehicle{path: path}
    34  }
    35  
    36  type HTTPVehicle struct {
    37  	url  string
    38  	path string
    39  }
    40  
    41  func (h *HTTPVehicle) Type() types.VehicleType {
    42  	return types.HTTP
    43  }
    44  
    45  func (h *HTTPVehicle) Path() string {
    46  	return h.path
    47  }
    48  
    49  func (h *HTTPVehicle) Read() ([]byte, error) {
    50  	ctx, cancel := context.WithTimeout(context.Background(), time.Second*20)
    51  	defer cancel()
    52  
    53  	uri, err := url.Parse(h.url)
    54  	if err != nil {
    55  		return nil, err
    56  	}
    57  
    58  	req, err := http.NewRequest(http.MethodGet, uri.String(), nil)
    59  	if err != nil {
    60  		return nil, err
    61  	}
    62  
    63  	if user := uri.User; user != nil {
    64  		password, _ := user.Password()
    65  		req.SetBasicAuth(user.Username(), password)
    66  	}
    67  
    68  	req = req.WithContext(ctx)
    69  
    70  	transport := &http.Transport{
    71  		// from http.DefaultTransport
    72  		MaxIdleConns:          100,
    73  		IdleConnTimeout:       90 * time.Second,
    74  		TLSHandshakeTimeout:   10 * time.Second,
    75  		ExpectContinueTimeout: 1 * time.Second,
    76  		DialContext: func(ctx context.Context, network, address string) (net.Conn, error) {
    77  			return dialer.DialContext(ctx, network, address)
    78  		},
    79  	}
    80  
    81  	client := http.Client{Transport: transport}
    82  	resp, err := client.Do(req)
    83  	if err != nil {
    84  		return nil, err
    85  	}
    86  	defer resp.Body.Close()
    87  
    88  	buf, err := io.ReadAll(resp.Body)
    89  	if err != nil {
    90  		return nil, err
    91  	}
    92  
    93  	return buf, nil
    94  }
    95  
    96  func NewHTTPVehicle(url string, path string) *HTTPVehicle {
    97  	return &HTTPVehicle{url, path}
    98  }