Skip to content

Commit

Permalink
Merge pull request #2 from labbsr0x/master
Browse files Browse the repository at this point in the history
Updates
  • Loading branch information
eabili0 authored Apr 17, 2019
2 parents 89f64e4 + 07ad324 commit 8b16b48
Show file tree
Hide file tree
Showing 5 changed files with 424 additions and 105 deletions.
7 changes: 7 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
language: go

go:
- 1.11.x

script:
- go test -v ./...
26 changes: 24 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,24 @@
# Goh
Utility lib for writing extremely simple webhooks in go.
# GoH
Utility lib for writing extremely simple webhooks in go, among other things.

# Packages

For now, GoH has four packages.

1. `gohclient`: http helper methods to easily communicate with a REST api written in go.

2. `gohcmd`: methods to ease out the proper creation of cmd utilities.

3. `gohserver`: http helper methods to make it easy to create webhooks.

4. `gohtypes`: helper types for handling with webhook constructs

# Examples

You can find good examples that use goh in the following repositories:

[Bindman DNS Webhook](http://github.com/labbsr0x/bindman-dns-webhook/)

[Bindman DNS Swarm Listener](https://github.com/labbsr0x/bindman-dns-swarm-listener)

[Bindman DNS Bind9 Manager](https://github.com/labbsr0x/bindman-dns-bind9)
99 changes: 65 additions & 34 deletions gohclient/gohclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@ package gohclient

import (
"bytes"
"io"
"io/ioutil"
"net/http"
"time"
"net/url"
"strings"

"github.com/go-errors/errors"
"github.com/sirupsen/logrus"
)

Expand All @@ -19,65 +22,93 @@ type API interface {

// Default defines a struct that handles with HTTP requests for a bindman webhook client
type Default struct {
// User agent used when communicating with the API
UserAgent string
// Request content type used when communicating with the API
ContentType string
Accept string
BaseURL *url.URL
HTTPClient *http.Client
}

// New instantiates a default goh client
func New(contentType, accept string) *Default {
return &Default{
ContentType: contentType,
Accept: accept,
// If a nil httpClient is provided, http.DefaultClient will be used.
func New(httpClient *http.Client, baseURL string) (*Default, error) {
if httpClient == nil {
httpClient = http.DefaultClient
}
if strings.TrimSpace(baseURL) == "" {
return nil, errors.New("base URL cannot be an empty string")
}
parsedURL, err := url.Parse(baseURL)
if err != nil {
return nil, err
}

return &Default{
BaseURL: parsedURL,
HTTPClient: httpClient,
}, nil
}

// Put wraps the call to http.NewRequest apis and properly submits a new HTTP POST request
func (c *Default) Put(url string, data []byte) (*http.Response, []byte, error) {
return c.request(url, "PUT", data)
func (c *Default) Put(path string, data []byte) (*http.Response, []byte, error) {
return c.request(path, "PUT", data)
}

// Post wraps the call to http.NewRequest apis and properly submits a new HTTP POST request
func (c *Default) Post(url string, data []byte) (*http.Response, []byte, error) {
return c.request(url, "POST", data)
func (c *Default) Post(path string, data []byte) (*http.Response, []byte, error) {
return c.request(path, "POST", data)
}

// Get wraps the call to http.NewRequest apis and properly submits a new HTTP GET request
func (c *Default) Get(url string) (*http.Response, []byte, error) {
return c.request(url, "GET", nil)
func (c *Default) Get(path string) (*http.Response, []byte, error) {
return c.request(path, "GET", nil)
}

// Delete wraps the call to http.NewRequest apis and properly submits a new HTTP DELETE request
func (c *Default) Delete(url string) (*http.Response, []byte, error) {
return c.request(url, "DELETE", nil)
func (c *Default) Delete(path string) (*http.Response, []byte, error) {
return c.request(path, "DELETE", nil)
}

var httpDo = (&http.Client{Timeout: time.Second * 10}).Do

// request defines a generic method to execute http requests
func (c *Default) request(url, method string, payload []byte) (httpResponse *http.Response, data []byte, err error) {
logrus.Debugf("Request body: %v", payload)
req, err := http.NewRequest(method, url, bytes.NewBuffer(payload))
if err == nil {
func (c *Default) request(path, method string, body []byte) (resp *http.Response, data []byte, err error) {
u, err := c.BaseURL.Parse(path)
if err != nil {
return
}

req, err := http.NewRequest(method, u.String(), bytes.NewBuffer(body))
if err != nil {
logrus.Errorf("HTTP request creation failed. err=%v", err)
return
}

if body != nil && strings.TrimSpace(c.ContentType) != "" {
req.Header.Set("Content-Type", c.ContentType)
}
if strings.TrimSpace(c.Accept) != "" {
req.Header.Set("Accept", c.Accept)
}
if strings.TrimSpace(c.UserAgent) != "" {
req.Header.Set("User-Agent", c.UserAgent)
}
logrus.Debugf("%v request=%v", method, req)

logrus.Debugf("%v request=%v", method, req)

httpResponse, err = httpDo(req)
if err == nil {
defer func() {
if closeError := httpResponse.Body.Close(); closeError != nil {
logrus.Errorf("HTTP %v response body close invocation failed. err=%v", method, err)
}
}()
logrus.Debugf("Response: %v", httpResponse)
data, _ = ioutil.ReadAll(httpResponse.Body)
logrus.Debugf("Response body: %v", data)
return
}
resp, err = c.HTTPClient.Do(req)
if err != nil {
logrus.Errorf("HTTP %v request invocation failed. err=%v", method, err)
return
}
logrus.Errorf("HTTP %v request creation failed. err=%v", method, err)
defer dClose(resp.Body)
logrus.Debugf("Response: %v", resp)
data, err = ioutil.ReadAll(resp.Body)
logrus.Debugf("Response body: %v", data)
return
}

func dClose(c io.Closer) {
if err := c.Close(); err != nil {
logrus.Errorf("HTTP response body close invocation failed. err=%v", err)
}
}
Loading

0 comments on commit 8b16b48

Please sign in to comment.