github.com/searKing/golang/go@v1.2.117/net/http/client.go (about)

     1  // Copyright 2022 The searKing Author. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package http
     6  
     7  import (
     8  	"context"
     9  	"io"
    10  	"net"
    11  	"net/http"
    12  	"net/url"
    13  	"strings"
    14  
    15  	"github.com/searKing/golang/go/net/http/httphost"
    16  	"github.com/searKing/golang/go/net/http/httpproxy"
    17  )
    18  
    19  type Client struct {
    20  	http.Client
    21  
    22  	Proxy *httpproxy.Proxy
    23  	Host  *httphost.Host
    24  }
    25  
    26  // Use adds middleware handlers to the transport.
    27  func (c *Client) Use(d ...RoundTripDecorator) *Client {
    28  	if len(d) == 0 {
    29  		return c
    30  	}
    31  	var rts RoundTripDecorators
    32  	rts = append(rts, d...)
    33  	c.Transport = rts.WrapRoundTrip(c.Transport)
    34  	// for chained call
    35  	return c
    36  }
    37  
    38  // parseURL is just url.Parse. It exists only so that url.Parse can be called
    39  // in places where url is shadowed for godoc. See https://golang.org/cl/49930.
    40  var parseURL = url.Parse
    41  
    42  // NewClient returns a http client wrapper behaves like http.Client,
    43  // sends HTTP Request to target by proxy url with Host replaced by proxyTarget
    44  //
    45  // u is the original url to send HTTP request, empty usually.
    46  // target is the resolver to resolve Host to send HTTP request,
    47  // that is replacing host in url(NOT HOST in http header) by address resolved by Host
    48  // fixedProxyUrl is proxy's url, like socks5://127.0.0.1:8080
    49  // fixedProxyTarget is as like gRPC Naming for proxy service discovery, with Host in TargetUrl replaced if not empty.
    50  func NewClient(u, hostTarget string, proxyUrl string, proxyTarget string) (*Client, error) {
    51  	tr := DefaultTransportWithDynamicHostAndProxy
    52  	if len(u) > 0 {
    53  		urlParsed, err := parseURL(u)
    54  		if err != nil {
    55  			return nil, err
    56  		}
    57  		hostname := urlParsed.Hostname()
    58  		if strings.Index(hostname, "unix:") == 0 {
    59  			tr = &http.Transport{
    60  				DisableCompression: true,
    61  				DialContext: func(ctx context.Context, network, addr string) (conn net.Conn, e error) {
    62  					return net.Dial("unix", urlParsed.Host)
    63  				},
    64  			}
    65  		}
    66  	}
    67  	client := http.Client{Transport: tr}
    68  	c := &Client{
    69  		Client: client,
    70  	}
    71  	if hostTarget != "" {
    72  		c.Host = &httphost.Host{
    73  			HostTarget:           hostTarget,
    74  			ReplaceHostInRequest: false,
    75  		}
    76  	}
    77  	if proxyUrl != "" {
    78  		c.Proxy = &httpproxy.Proxy{
    79  			ProxyUrl:    proxyUrl,
    80  			ProxyTarget: proxyTarget,
    81  		}
    82  	}
    83  	return c, nil
    84  }
    85  
    86  // NewClientWithTarget returns a Client with http.Client and host replaced by resolver.Host
    87  // target is the resolver to resolve Host to send HTTP request,
    88  // that is replacing host in url(NOT HOST in http header) by address resolved by Host
    89  func NewClientWithTarget(target string) *Client {
    90  	cli, _ := NewClient("", target, "", "")
    91  	return cli
    92  }
    93  
    94  // NewClientWithProxy returns a Client with http.Client with proxy set by resolver.Host
    95  // TargetUrl is proxy's url, like socks5://127.0.0.1:8080
    96  // Host is proxy's addr, replace the HOST in TargetUrl if not empty
    97  func NewClientWithProxy(proxyUrl string, proxyTarget string) *Client {
    98  	cli, _ := NewClient("", "", proxyUrl, proxyTarget)
    99  	return cli
   100  }
   101  
   102  func NewClientWithUnixDisableCompression(u string) (*Client, error) {
   103  	return NewClient(u, "", "", "")
   104  }
   105  
   106  func (c *Client) Do(req *http.Request) (_ *http.Response, err error) {
   107  	return c.Client.Do(RequestWithHostTarget(RequestWithProxyTarget(req, c.Proxy), c.Host))
   108  }
   109  
   110  func (c *Client) Head(url string) (resp *http.Response, err error) {
   111  	req, err := http.NewRequest(http.MethodHead, url, nil)
   112  	if err != nil {
   113  		return nil, err
   114  	}
   115  	return c.Do(req)
   116  }
   117  
   118  func (c *Client) Get(url string) (resp *http.Response, err error) {
   119  	req, err := http.NewRequest(http.MethodGet, url, nil)
   120  	if err != nil {
   121  		return nil, err
   122  	}
   123  	return c.Do(req)
   124  }
   125  
   126  func (c *Client) Post(url string, contentType string, body io.Reader) (resp *http.Response, err error) {
   127  	req, err := http.NewRequest(http.MethodPost, url, body)
   128  	if err != nil {
   129  		return nil, err
   130  	}
   131  	req.Header.Set("Content-Type", contentType)
   132  	return c.Do(req)
   133  }
   134  
   135  func (c *Client) PostForm(url string, data url.Values) (resp *http.Response, err error) {
   136  	return c.Post(url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode()))
   137  }
   138  
   139  func Head(url string) (resp *http.Response, err error) {
   140  	client, err := NewClientWithUnixDisableCompression(url)
   141  	if err != nil {
   142  		return nil, err
   143  	}
   144  	return client.Head(url)
   145  
   146  }
   147  
   148  func Get(url string) (resp *http.Response, err error) {
   149  	client, err := NewClientWithUnixDisableCompression(url)
   150  	if err != nil {
   151  		return nil, err
   152  	}
   153  	return client.Get(url)
   154  }
   155  
   156  func Post(url, contentType string, body io.Reader) (resp *http.Response, err error) {
   157  	client, err := NewClientWithUnixDisableCompression(url)
   158  	if err != nil {
   159  		return nil, err
   160  	}
   161  	return client.Post(url, contentType, body)
   162  }
   163  
   164  func PostForm(url string, data url.Values) (resp *http.Response, err error) {
   165  	client, err := NewClientWithUnixDisableCompression(url)
   166  	if err != nil {
   167  		return nil, err
   168  	}
   169  	return client.PostForm(url, data)
   170  }