gohclient.go raw

   1  package gohclient
   2  
   3  import (
   4  	"bytes"
   5  	"io"
   6  	"io/ioutil"
   7  	"net/http"
   8  	"net/url"
   9  	"strings"
  10  
  11  	"github.com/go-errors/errors"
  12  	"github.com/sirupsen/logrus"
  13  )
  14  
  15  // API defines an interface for helper methods that encapsulates http requests complexities
  16  type API interface {
  17  	Put(url string, data []byte) (*http.Response, []byte, error)
  18  	Post(url string, data []byte) (*http.Response, []byte, error)
  19  	Get(url string) (*http.Response, []byte, error)
  20  	Delete(url string) (*http.Response, []byte, error)
  21  }
  22  
  23  // Default defines a struct that handles with HTTP requests for a bindman webhook client
  24  type Default struct {
  25  	// User agent used when communicating with the API
  26  	UserAgent string
  27  	// Request content type used when communicating with the API
  28  	ContentType string
  29  	Accept      string
  30  	BaseURL     *url.URL
  31  	HTTPClient  *http.Client
  32  }
  33  
  34  // New instantiates a default goh client
  35  // If a nil httpClient is provided, http.DefaultClient will be used.
  36  func New(httpClient *http.Client, baseURL string) (*Default, error) {
  37  	if httpClient == nil {
  38  		httpClient = http.DefaultClient
  39  	}
  40  	if strings.TrimSpace(baseURL) == "" {
  41  		return nil, errors.New("base URL cannot be an empty string")
  42  	}
  43  	parsedURL, err := url.Parse(baseURL)
  44  	if err != nil {
  45  		return nil, err
  46  	}
  47  
  48  	return &Default{
  49  		BaseURL:    parsedURL,
  50  		HTTPClient: httpClient,
  51  	}, nil
  52  }
  53  
  54  // Put wraps the call to http.NewRequest apis and properly submits a new HTTP POST request
  55  func (c *Default) Put(path string, data []byte) (*http.Response, []byte, error) {
  56  	return c.request(path, "PUT", data)
  57  }
  58  
  59  // Post wraps the call to http.NewRequest apis and properly submits a new HTTP POST request
  60  func (c *Default) Post(path string, data []byte) (*http.Response, []byte, error) {
  61  	return c.request(path, "POST", data)
  62  }
  63  
  64  // Get wraps the call to http.NewRequest apis and properly submits a new HTTP GET request
  65  func (c *Default) Get(path string) (*http.Response, []byte, error) {
  66  	return c.request(path, "GET", nil)
  67  }
  68  
  69  // Delete wraps the call to http.NewRequest apis and properly submits a new HTTP DELETE request
  70  func (c *Default) Delete(path string) (*http.Response, []byte, error) {
  71  	return c.request(path, "DELETE", nil)
  72  }
  73  
  74  // request defines a generic method to execute http requests
  75  func (c *Default) request(path, method string, body []byte) (resp *http.Response, data []byte, err error) {
  76  	u, err := c.BaseURL.Parse(path)
  77  	if err != nil {
  78  		return
  79  	}
  80  
  81  	req, err := http.NewRequest(method, u.String(), bytes.NewBuffer(body))
  82  	if err != nil {
  83  		logrus.Errorf("HTTP request creation failed. err=%v", err)
  84  		return
  85  	}
  86  
  87  	if body != nil && strings.TrimSpace(c.ContentType) != "" {
  88  		req.Header.Set("Content-Type", c.ContentType)
  89  	}
  90  	if strings.TrimSpace(c.Accept) != "" {
  91  		req.Header.Set("Accept", c.Accept)
  92  	}
  93  	if strings.TrimSpace(c.UserAgent) != "" {
  94  		req.Header.Set("User-Agent", c.UserAgent)
  95  	}
  96  	logrus.Debugf("%v request=%v", method, req)
  97  
  98  	resp, err = c.HTTPClient.Do(req)
  99  	if err != nil {
 100  		logrus.Errorf("HTTP  %v request invocation failed. err=%v", method, err)
 101  		return
 102  	}
 103  	defer dClose(resp.Body)
 104  	logrus.Debugf("Response: %v", resp)
 105  	data, err = ioutil.ReadAll(resp.Body)
 106  	logrus.Debugf("Response body: %v", data)
 107  	return
 108  }
 109  
 110  func dClose(c io.Closer) {
 111  	if err := c.Close(); err != nil {
 112  		logrus.Errorf("HTTP response body close invocation failed. err=%v", err)
 113  	}
 114  }
 115