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