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