• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

odwrtw / polochon / 10577485076

27 Aug 2024 11:48AM UTC coverage: 67.74% (-0.2%) from 67.911%
10577485076

push

github

PouuleT
Improve context handling in polochonfs

* Handle fs stop from signal
* Handle stop from program reading the data
* Handle HTTP timeouts

2692 of 3974 relevant lines covered (67.74%)

0.75 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

78.64
/lib/papi/client.go
1
package papi
2

3
import (
4
        "bytes"
5
        "encoding/json"
6
        "fmt"
7
        "io"
8
        "net/http"
9
        "net/url"
10
        "time"
11
)
12

13
// Resource is an interface to identify a resource
14
type Resource interface {
15
        uri() (string, error)
16
        getDetails(c *Client) error
17
}
18

19
// Downloadable is an interface for a downloadable content
20
type Downloadable interface {
21
        Resource
22
        downloadURL() (string, error)
23
}
24

25
type basicAuth struct {
26
        username string
27
        password string
28
}
29

30
// Client of the polochon API
31
type Client struct {
32
        endpoint  string
33
        token     string
34
        basicAuth *basicAuth
35
        timeout   time.Duration
36
}
37

38
// New returns a new Client, url is the base url of
39
// your polochon API
40
func New(endpoint string) (*Client, error) {
1✔
41
        if _, err := url.Parse(endpoint); err != nil {
1✔
42
                return nil, err
×
43
        }
×
44

45
        return &Client{
1✔
46
                endpoint: endpoint,
1✔
47
        }, nil
1✔
48
}
49

50
// SetToken sets the token
51
func (c *Client) SetToken(token string) {
1✔
52
        c.token = token
1✔
53
}
1✔
54

55
// SetTimeout sets the HTTP timeout
56
func (c *Client) SetTimeout(timeout time.Duration) {
×
57
        c.timeout = timeout
×
58
}
×
59

60
// SetBasicAuth set the basic auth details
61
func (c *Client) SetBasicAuth(username, password string) {
1✔
62
        c.basicAuth = &basicAuth{
1✔
63
                username: username,
1✔
64
                password: password,
1✔
65
        }
1✔
66
}
1✔
67

68
// GetDetails get the detailed informations of a resource
69
func (c *Client) GetDetails(resource Resource) error {
×
70
        return resource.getDetails(c)
×
71
}
×
72

73
// URI returns a resource URI
74
func (c *Client) URI(resource Resource) (string, error) {
×
75
        uri, err := resource.uri()
×
76
        if err != nil {
×
77
                return "", err
×
78
        }
×
79

80
        return c.endpoint + "/" + uri, nil
×
81
}
82

83
// DownloadURL returns the download URL of a downloadable content
84
func (c *Client) DownloadURL(target Downloadable) (string, error) {
1✔
85
        url, err := target.downloadURL()
1✔
86
        if err != nil {
2✔
87
                return "", err
1✔
88
        }
1✔
89

90
        return c.endpoint + "/" + url, nil
1✔
91
}
92

93
// DownloadURLWithToken returns the url with the token
94
func (c *Client) DownloadURLWithToken(target Downloadable) (string, error) {
1✔
95
        url, err := c.DownloadURL(target)
1✔
96
        if err != nil {
2✔
97
                return "", err
1✔
98
        }
1✔
99

100
        if c.token != "" {
2✔
101
                url += "?token=" + c.token
1✔
102
        }
1✔
103

104
        return url, nil
1✔
105
}
106

107
// Delete deletes a ressource
108
func (c *Client) Delete(target Resource) error {
1✔
109
        url, err := target.uri()
1✔
110
        if err != nil {
1✔
111
                return err
×
112
        }
×
113

114
        return c.delete(fmt.Sprintf("%s/%s", c.endpoint, url))
1✔
115
}
116

117
func (c *Client) get(url string, result interface{}) error {
1✔
118
        return c.request("GET", url, nil, result)
1✔
119
}
1✔
120

121
func (c *Client) post(url string, data, result interface{}) error {
1✔
122
        buf := &bytes.Buffer{}
1✔
123
        err := json.NewEncoder(buf).Encode(data)
1✔
124
        if err != nil {
1✔
125
                return err
×
126
        }
×
127

128
        return c.request("POST", url, buf, result)
1✔
129
}
130

131
func (c *Client) delete(url string) error {
1✔
132
        return c.request("DELETE", url, nil, nil)
1✔
133
}
1✔
134

135
func (c *Client) request(httpType, url string, data io.Reader, result interface{}) error {
1✔
136
        req, err := http.NewRequest(httpType, url, data)
1✔
137
        if err != nil {
1✔
138
                return err
×
139
        }
×
140
        req.Header.Add("User-Agent", "papi")
1✔
141

1✔
142
        if c.token != "" {
2✔
143
                req.Header.Add("X-Auth-Token", c.token)
1✔
144
        }
1✔
145

146
        if c.basicAuth != nil {
2✔
147
                req.SetBasicAuth(c.basicAuth.username, c.basicAuth.password)
1✔
148
        }
1✔
149

150
        httpClient := &http.Client{Timeout: c.timeout}
1✔
151
        resp, err := httpClient.Do(req)
1✔
152
        if err != nil {
1✔
153
                return err
×
154
        }
×
155
        defer resp.Body.Close()
1✔
156

1✔
157
        switch resp.StatusCode {
1✔
158
        case http.StatusOK:
1✔
159
                // sometimes there's nothing in the Body and we don't wanna parse it
1✔
160
                if result == nil {
2✔
161
                        return nil
1✔
162
                }
1✔
163
                return json.NewDecoder(resp.Body).Decode(&result)
1✔
164
        case http.StatusNotFound:
1✔
165
                // return the not found error
1✔
166
                return ErrResourceNotFound
1✔
167
        default:
1✔
168
                // default polochon error is a JSON with an error field
1✔
169
                polochonErr := struct {
1✔
170
                        Error string `json:"error"`
1✔
171
                }{
1✔
172
                        Error: "Unknown error",
1✔
173
                }
1✔
174
                // If the decode returns an error we ignore it, the default "Unknown
1✔
175
                // error" message will be returned
1✔
176
                json.NewDecoder(resp.Body).Decode(&polochonErr)
1✔
177
                return fmt.Errorf("papi: HTTP error status %s: %s", resp.Status, polochonErr.Error)
1✔
178
        }
179
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc