ducky/subscriptions

Paddy 2015-09-30 Parent:8eb19bcbf17d Child:7eef47ecc01c

14:fb2c0e498e37 Go to Latest

ducky/subscriptions/client/client.go

Update with comments for all exported functions. We now have golint-approved comments for all the exported functions in the subscriptions package. Next challenge: all the sub-packages!

History
paddy@7 1 package client
paddy@7 2
paddy@7 3 import (
paddy@7 4 "bytes"
paddy@7 5 "encoding/json"
paddy@7 6 "errors"
paddy@9 7 "fmt"
paddy@7 8 "io"
paddy@7 9 "net/http"
paddy@7 10 "strings"
paddy@7 11 "time"
paddy@7 12
paddy@9 13 commonAPI "code.secondbit.org/api.hg"
paddy@7 14 "code.secondbit.org/uuid.hg"
paddy@7 15
paddy@7 16 "code.secondbit.org/ducky/subscriptions.hg/api"
paddy@7 17 )
paddy@7 18
paddy@7 19 var (
paddy@7 20 ErrNilClient = errors.New("nil client wrapper")
paddy@7 21 ErrNilHTTPClient = errors.New("nil client")
paddy@7 22 )
paddy@7 23
paddy@7 24 type Client struct {
paddy@7 25 client *http.Client
paddy@7 26 address string
paddy@7 27 ID uuid.ID
paddy@7 28 }
paddy@7 29
paddy@7 30 func New(address string, id uuid.ID) *Client {
paddy@7 31 address = strings.TrimRight(address, "/")
paddy@7 32 return &Client{
paddy@7 33 address: address,
paddy@7 34 client: &http.Client{},
paddy@7 35 ID: id,
paddy@7 36 }
paddy@7 37 }
paddy@7 38
paddy@7 39 func (c *Client) do(method, url string, request interface{}, scopes []string, subject uuid.ID) (api.Response, error) {
paddy@7 40 if c == nil {
paddy@7 41 return api.Response{}, ErrNilClient
paddy@7 42 }
paddy@7 43 if c.client == nil {
paddy@7 44 return api.Response{}, ErrNilHTTPClient
paddy@7 45 }
paddy@7 46 var response api.Response
paddy@7 47 if !strings.HasPrefix(url, "http") {
paddy@7 48 url = strings.TrimLeft(url, "/")
paddy@7 49 url = "/" + url
paddy@7 50 url = c.address + url
paddy@7 51 }
paddy@7 52 var body io.Reader
paddy@7 53 if request != nil {
paddy@7 54 data, err := json.Marshal(request)
paddy@7 55 if err != nil {
paddy@7 56 return response, err
paddy@7 57 }
paddy@7 58 body = bytes.NewBuffer(data)
paddy@7 59 }
paddy@7 60 req, err := http.NewRequest(method, url, body)
paddy@7 61 if err != nil {
paddy@7 62 return response, err
paddy@7 63 }
paddy@7 64 req.Header.Set("Ducky-Scope", strings.Join(scopes, " "))
paddy@7 65 req.Header.Set("Ducky-Issuer", c.ID.String())
paddy@7 66 if subject != nil {
paddy@7 67 req.Header.Set("Ducky-Subject", subject.String())
paddy@7 68 }
paddy@7 69 req.Header.Set("Ducky-Expires", time.Now().Add(time.Hour).String())
paddy@7 70 req.Header.Set("Ducky-Issued-At", time.Now().String())
paddy@7 71 req.Header.Set("Ducky-Not-Before", time.Now().Add(-5*time.Minute).String())
paddy@7 72 resp, err := c.client.Do(req)
paddy@7 73 if err != nil {
paddy@7 74 return response, err
paddy@7 75 }
paddy@7 76 defer resp.Body.Close()
paddy@7 77 switch resp.Header.Get("Content-Type") {
paddy@7 78 case "application/json":
paddy@7 79 dec := json.NewDecoder(resp.Body)
paddy@7 80 err = dec.Decode(&response)
paddy@7 81 if err != nil {
paddy@7 82 return response, err
paddy@7 83 }
paddy@7 84 default:
paddy@7 85 dec := json.NewDecoder(resp.Body)
paddy@7 86 err = dec.Decode(&response)
paddy@7 87 if err != nil {
paddy@7 88 return response, err
paddy@7 89 }
paddy@7 90 }
paddy@9 91 if len(response.Errors) > 0 {
paddy@9 92 return response, httpErrors(response.Errors)
paddy@9 93 }
paddy@7 94 return response, nil
paddy@7 95 }
paddy@7 96
paddy@9 97 type httpErrors []commonAPI.RequestError
paddy@9 98
paddy@9 99 func (h httpErrors) Error() string {
paddy@9 100 return fmt.Sprintf("%+#v", h)
paddy@9 101 }
paddy@9 102
paddy@7 103 func (c *Client) Get(url string, scopes []string, subject uuid.ID) (api.Response, error) {
paddy@7 104 return c.do("GET", url, nil, scopes, subject)
paddy@7 105 }
paddy@7 106
paddy@7 107 func (c *Client) Post(url string, request interface{}, scopes []string, subject uuid.ID) (api.Response, error) {
paddy@7 108 return c.do("POST", url, request, scopes, subject)
paddy@7 109 }
paddy@7 110
paddy@7 111 func (c *Client) Patch(url string, request interface{}, scopes []string, subject uuid.ID) (api.Response, error) {
paddy@7 112 return c.do("PATCH", url, request, scopes, subject)
paddy@7 113 }