ducky/subscriptions

Paddy 2015-07-13 Child:8eb19bcbf17d

7:9e138933e4ce Go to Latest

ducky/subscriptions/client/client.go

Create a client for working with subscriptions. We mostly copied our code.secondbit.org/auth.hg/client package to create a simple client library for communicating with our Subscriptions API. Right now, the client only has support for creating a subscription. It remains untested, but it builds.

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