-
Notifications
You must be signed in to change notification settings - Fork 1
/
fetch.go
83 lines (70 loc) · 1.75 KB
/
fetch.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
package tpb
import (
"context"
"encoding/json"
"fmt"
"net/http"
"time"
)
func (c *Client) fetchTorrents(ctx context.Context, path string) ([]*Torrent, error) {
var torrents []*Torrent
err := c.fetch(ctx, path, &torrents)
if err != nil {
return nil, err
}
// If the search returned no results, there will be one "fake" torrent
// in the results which name is: "No results returned"
if len(torrents) == 1 && torrents[0].Name == "No results returned" {
return []*Torrent{}, nil
}
return torrents, nil
}
// fetch will try to GET the path, trying all the endpoints if needed, and
// unmarshal the results in the data interface
func (c *Client) fetch(ctx context.Context, path string, data interface{}) error {
var err error
for i := 0; i < c.MaxTries; i++ {
endpoint := c.endpoints.best()
if endpoint == nil {
return ErrMissingEndpoint
}
timeoutCtx, cancel := context.WithTimeout(ctx, c.EndpointTimeout)
defer cancel()
err = get(timeoutCtx, endpoint.baseURL+path, &data)
if err == nil {
return nil
}
endpoint.lastFailure = time.Now()
// Stop if the global context is done
if ctx.Err() != nil {
err = ctx.Err()
break
}
}
return err
}
// get will GET the url and unmarshal the results in the data interface
func get(ctx context.Context, url string, data interface{}) error {
var err error
done := make(chan struct{})
go func() {
defer close(done)
var resp *http.Response
resp, err = http.Get(url)
if err != nil {
return
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
err = fmt.Errorf("got status %d when making the request", resp.StatusCode)
return
}
err = json.NewDecoder(resp.Body).Decode(&data)
}()
select {
case <-done:
return err
case <-ctx.Done():
return ctx.Err()
}
}