ducky/subscriptions

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

13:1ff031bebf9e Go to Latest

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.

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