github.com/metacubex/mihomo@v1.18.5/component/http/http.go (about)

     1  package http
     2  
     3  import (
     4  	"context"
     5  	"crypto/tls"
     6  	"io"
     7  	"net"
     8  	"net/http"
     9  	URL "net/url"
    10  	"runtime"
    11  	"strings"
    12  	"time"
    13  
    14  	"github.com/metacubex/mihomo/component/ca"
    15  	C "github.com/metacubex/mihomo/constant"
    16  	"github.com/metacubex/mihomo/listener/inner"
    17  )
    18  
    19  func HttpRequest(ctx context.Context, url, method string, header map[string][]string, body io.Reader) (*http.Response, error) {
    20  	return HttpRequestWithProxy(ctx, url, method, header, body, "")
    21  }
    22  
    23  func HttpRequestWithProxy(ctx context.Context, url, method string, header map[string][]string, body io.Reader, specialProxy string) (*http.Response, error) {
    24  	method = strings.ToUpper(method)
    25  	urlRes, err := URL.Parse(url)
    26  	if err != nil {
    27  		return nil, err
    28  	}
    29  
    30  	req, err := http.NewRequest(method, urlRes.String(), body)
    31  	for k, v := range header {
    32  		for _, v := range v {
    33  			req.Header.Add(k, v)
    34  		}
    35  	}
    36  
    37  	if _, ok := header["User-Agent"]; !ok {
    38  		req.Header.Set("User-Agent", C.UA)
    39  	}
    40  
    41  	if err != nil {
    42  		return nil, err
    43  	}
    44  
    45  	if user := urlRes.User; user != nil {
    46  		password, _ := user.Password()
    47  		req.SetBasicAuth(user.Username(), password)
    48  	}
    49  
    50  	req = req.WithContext(ctx)
    51  
    52  	transport := &http.Transport{
    53  		// from http.DefaultTransport
    54  		DisableKeepAlives:     runtime.GOOS == "android",
    55  		MaxIdleConns:          100,
    56  		IdleConnTimeout:       30 * time.Second,
    57  		TLSHandshakeTimeout:   10 * time.Second,
    58  		ExpectContinueTimeout: 1 * time.Second,
    59  		DialContext: func(ctx context.Context, network, address string) (net.Conn, error) {
    60  			if conn, err := inner.HandleTcp(address, specialProxy); err == nil {
    61  				return conn, nil
    62  			} else {
    63  				d := net.Dialer{}
    64  				return d.DialContext(ctx, network, address)
    65  			}
    66  		},
    67  		TLSClientConfig: ca.GetGlobalTLSConfig(&tls.Config{}),
    68  	}
    69  
    70  	client := http.Client{Transport: transport}
    71  	return client.Do(req)
    72  }