-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathclient.go
98 lines (79 loc) · 2.29 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
package rawg
import (
"context"
"encoding/json"
"fmt"
"golang.org/x/time/rate"
"io/ioutil"
"net/http"
)
const apiBaseUrl = "https://api.rawg.io/api"
// RawgError represents information about errors
type RawgError struct {
HttpCode int // HTTP status code (https://en.wikipedia.org/wiki/List_of_HTTP_status_codes)
Url string // URL of RAWG endpoint associated with callable function
Body string // Raw body of response
Message string // Any comment
}
// Error() converts error to string
func (e *RawgError) Error() string {
return fmt.Sprintf("Http code: %d, url: %s, body: %s, message: %s", e.HttpCode, e.Url, e.Body, e.Message)
}
// Client to interract with RAWG API
type Client struct {
baseUrl string
client *http.Client
config *Config
rateLimiter *rate.Limiter
}
// NewClient creates new Client to interract with RAWG API
func NewClient(client *http.Client, config *Config) *Client {
if config.Rps == 0 {
config.Rps = 5
}
if config.Language == "" {
config.Language = "en"
}
return &Client{
baseUrl: apiBaseUrl,
client: client,
config: config,
rateLimiter: rate.NewLimiter(rate.Limit(config.Rps), config.Rps),
}
}
func (api *Client) get(ctx context.Context, path string, params map[string]interface{}, responseModel interface{}) error {
fullPath := api.baseUrl + path
if err := api.rateLimiter.Wait(ctx); err != nil {
return err
}
req, e := http.NewRequestWithContext(ctx, http.MethodGet, fullPath, nil)
if e != nil {
return e
}
req.Header.Add("content-type", "application/json;charset=utf-8")
q := req.URL.Query()
q.Add("key", api.config.ApiKey)
q.Add("lang", api.config.Language)
for param, value := range params {
q.Add(param, fmt.Sprintf("%v", value))
}
req.URL.RawQuery = q.Encode()
resp, err := api.client.Do(req)
if err != nil {
return &RawgError{http.StatusServiceUnavailable, path, "", err.Error()}
}
if resp != nil {
defer resp.Body.Close()
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return &RawgError{resp.StatusCode, path, string(body), err.Error()}
}
if resp.StatusCode != http.StatusOK {
return &RawgError{resp.StatusCode, path, string(body), ""}
}
if err := json.Unmarshal(body, responseModel); err != nil {
return fmt.Errorf("could not decode the data: %s", err)
}
return nil
}