ducky/subscriptions
ducky/subscriptions/client/client.go
Add golint comments. Comment on some more of our exported types, functions, and variables, both to make golint happy and because uncommented code never ever ends well.
| 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 } |