github.com/go-board/x-go@v0.1.2-0.20220610024734-db1323f6cb15/xnet/xhttp/xrequest/http.go (about)

     1  package xrequest
     2  
     3  import (
     4  	"context"
     5  	"net/http"
     6  	"net/url"
     7  )
     8  
     9  // Client is a client to perform http request and retrieve http response.
    10  // Field client is *http.Client that real perform request.
    11  // Field interceptors is chain of Interceptor to hook client.
    12  type Client struct {
    13  	client       *http.Client
    14  	interceptors []Interceptor
    15  	baseHost     string
    16  }
    17  
    18  var DefaultClient = &Client{
    19  	client: http.DefaultClient,
    20  }
    21  
    22  // NewHttpClient create new client.
    23  func NewHttpClient(client *http.Client, baseHost string, interceptors ...Interceptor) *Client {
    24  	// try set client.Transport first
    25  	if client.Transport == nil {
    26  		client.Transport = http.DefaultTransport
    27  	}
    28  	// wrapper client.Transport
    29  	client.Transport = ComposeInterceptor(client.Transport, interceptors...)
    30  	return &Client{client: client, interceptors: interceptors, baseHost: baseHost}
    31  }
    32  
    33  func (c *Client) newRequest(ctx context.Context, method string, rawurl string, body RequestBody, options ...RequestOption) (*http.Request, error) {
    34  	if c.baseHost != "" {
    35  		u, err := url.Parse(rawurl)
    36  		if err == nil {
    37  			rawurl = c.baseHost + u.RequestURI()
    38  		}
    39  	}
    40  	r, err := http.NewRequestWithContext(ctx, method, rawurl, body)
    41  	if err != nil {
    42  		return nil, err
    43  	}
    44  	for _, option := range options {
    45  		option(r)
    46  	}
    47  	if body != nil {
    48  		r.Header.Set("Content-Type", body.ContentType())
    49  		if encoding := body.ContentEncoding(); encoding != nil {
    50  			r.Header.Set("Content-Encoding", *encoding)
    51  		}
    52  	}
    53  	return r, nil
    54  }
    55  
    56  func (c *Client) doRequest(req *http.Request) (*Response, error) {
    57  	response, err := c.client.Do(req)
    58  	if err != nil {
    59  		return nil, err
    60  	}
    61  	return newResponse(response), nil
    62  }
    63  
    64  func (c *Client) perform(ctx context.Context, method string, rawurl string, body RequestBody, options ...RequestOption) (*Response, error) {
    65  	r, err := c.newRequest(ctx, method, rawurl, body, options...)
    66  	if err != nil {
    67  		return nil, err
    68  	}
    69  	return c.doRequest(r)
    70  }
    71  
    72  // Head do HEAD request.
    73  func (c *Client) Head(ctx context.Context, url string, options ...RequestOption) (*Response, error) {
    74  	return c.perform(ctx, http.MethodHead, url, nil, options...)
    75  }
    76  
    77  // Connect do CONNECT request.
    78  func (c *Client) Connect(ctx context.Context, url string, options ...RequestOption) (*Response, error) {
    79  	return c.perform(ctx, http.MethodConnect, url, nil, options...)
    80  }
    81  
    82  // Options do OPTIONS request.
    83  func (c *Client) Options(ctx context.Context, url string, options ...RequestOption) (*Response, error) {
    84  	return c.perform(ctx, http.MethodConnect, url, nil, options...)
    85  }
    86  
    87  // Trace do TRACE request.
    88  func (c *Client) Trace(ctx context.Context, url string, options ...RequestOption) (*Response, error) {
    89  	return c.perform(ctx, http.MethodTrace, url, nil, options...)
    90  }
    91  
    92  // Get do GET request.
    93  func (c *Client) Get(ctx context.Context, url string, options ...RequestOption) (*Response, error) {
    94  	return c.perform(ctx, http.MethodGet, url, nil, options...)
    95  }
    96  
    97  // Post do POST request.
    98  func (c *Client) Post(ctx context.Context, url string, body RequestBody, options ...RequestOption) (*Response, error) {
    99  	return c.perform(ctx, http.MethodPost, url, body, options...)
   100  }
   101  
   102  // Put do PUT request.
   103  func (c *Client) Put(ctx context.Context, url string, body RequestBody, options ...RequestOption) (*Response, error) {
   104  	return c.perform(ctx, http.MethodPut, url, body, options...)
   105  }
   106  
   107  // Patch do PATCH request.
   108  func (c *Client) Patch(ctx context.Context, url string, body RequestBody, options ...RequestOption) (*Response, error) {
   109  	return c.perform(ctx, http.MethodPatch, url, body, options...)
   110  }
   111  
   112  // Delete do DELETE request.
   113  func (c *Client) Delete(ctx context.Context, url string, body RequestBody, options ...RequestOption) (*Response, error) {
   114  	return c.perform(ctx, http.MethodDelete, url, body, options...)
   115  }
   116  
   117  // Head do HEAD request.
   118  func Head(ctx context.Context, url string, options ...RequestOption) (*Response, error) {
   119  	return DefaultClient.Head(ctx, url, options...)
   120  }
   121  
   122  // Connect do CONNECT request.
   123  func Connect(ctx context.Context, url string, options ...RequestOption) (*Response, error) {
   124  	return DefaultClient.Connect(ctx, url, options...)
   125  }
   126  
   127  // Options do OPTIONS request.
   128  func Options(ctx context.Context, url string, options ...RequestOption) (*Response, error) {
   129  	return DefaultClient.Options(ctx, url, options...)
   130  }
   131  
   132  // Trace do TRACE request.
   133  func Trace(ctx context.Context, url string, options ...RequestOption) (*Response, error) {
   134  	return DefaultClient.Trace(ctx, url, options...)
   135  }
   136  
   137  // Get do GET request.
   138  func Get(ctx context.Context, url string, options ...RequestOption) (*Response, error) {
   139  	return DefaultClient.Get(ctx, url, options...)
   140  }
   141  
   142  // Post do POST request.
   143  func Post(ctx context.Context, url string, body RequestBody, options ...RequestOption) (*Response, error) {
   144  	return DefaultClient.Post(ctx, url, body, options...)
   145  }
   146  
   147  // Put do PUT request.
   148  func Put(ctx context.Context, url string, body RequestBody, options ...RequestOption) (*Response, error) {
   149  	return DefaultClient.Put(ctx, url, body, options...)
   150  }
   151  
   152  // Patch do PATCH request.
   153  func Patch(ctx context.Context, url string, body RequestBody, options ...RequestOption) (*Response, error) {
   154  	return DefaultClient.Patch(ctx, url, body, options...)
   155  }
   156  
   157  // Delete do DELETE request.
   158  func Delete(ctx context.Context, url string, body RequestBody, options ...RequestOption) (*Response, error) {
   159  	return DefaultClient.Delete(ctx, url, body, options...)
   160  }