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 }