-
Notifications
You must be signed in to change notification settings - Fork 2
/
client.go
104 lines (80 loc) · 2.24 KB
/
client.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
package fitbit
import (
"context"
"encoding/json"
"errors"
"log"
"net/http"
"net/url"
"time"
"github.com/byonchev/go-fitbit/internal/api"
"github.com/byonchev/go-fitbit/internal/auth"
)
const baseURL = "https://api.fitbit.com"
const timeout = 30 * time.Second
// Client is used to access the Fitbit API
type Client struct {
authHandler *auth.Handler
}
// NewClient creates new API client
func NewClient(config Config) *Client {
tokenStorage := auth.NewFileTokenStorage(config.TokenPath)
authHandler := auth.NewHandler(
config.ClientID,
config.ClientSecret,
config.Scopes,
config.CallbackServerPort,
tokenStorage,
)
return &Client{authHandler: authHandler}
}
func (client Client) getResource(path string, params url.Values, out interface{}) error {
context, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
httpClient, err := client.authHandler.Client(context)
if err != nil {
return err
}
url := client.createURL(path, params)
response, err := httpClient.Get(url.String())
if err != nil {
return err
}
defer response.Body.Close()
return client.handleResponse(response, out)
}
func (client Client) handleResponse(response *http.Response, out interface{}) error {
statusCode := response.StatusCode
decoder := json.NewDecoder(response.Body)
if statusCode == http.StatusOK {
return decoder.Decode(out)
}
var result api.GenericResponse
decoder.Decode(&result)
if len(result.Errors) == 0 {
log.Printf("received status code %d\n", statusCode)
}
for _, err := range result.Errors {
log.Printf("[%d] %s: %s\n", statusCode, err.Type, err.Message)
}
if statusCode == http.StatusUnauthorized {
client.authHandler.Reset()
return errors.New("authorization error")
}
if statusCode == http.StatusTooManyRequests {
return errors.New("too many requests")
}
if statusCode >= 400 && statusCode < 500 {
return errors.New("bad request")
}
return errors.New("unknown error")
}
func (client Client) createURL(path string, params url.Values) *url.URL {
url, err := url.Parse(baseURL)
if err != nil {
panic(err)
}
url.Path = path + ".json"
url.RawQuery = params.Encode()
return url
}