/
api.go
95 lines (79 loc) · 2.56 KB
/
api.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
// Package api provides different types of functions for making http request and reading responses.
package api
import (
"fmt"
"github.com/pkg/errors"
"github.com/spf13/viper"
"io"
"io/ioutil"
"net/http"
"strconv"
)
const (
headerToken = "X-SBG-Auth-Token"
headerMaxOffset = "X-Total-Matching-Query"
headerJSONContentTypeKey = "Content-Type"
headerJSONContentTypeValue = "application/json"
UrlBase = "https://cgc-api.sbgenomics.com/v2"
UrlProjects = UrlBase + "/projects"
UrlFiles = UrlBase + "/files"
)
// CGCRequest will make a http request based on method, url & body.
// It will return http response only if it's 200.
// If it is not 200, error with body message will be returned
func CGCRequest(method string, url string, body io.Reader) (resp *http.Response, err error) {
req, err := http.NewRequest(method, url, body)
if err != nil {
return nil, errors.Wrap(err, "cannot initialize *Request")
}
// add mandatory headers
req.Header.Set(headerToken, viper.GetString("token"))
req.Header.Set(headerJSONContentTypeKey, headerJSONContentTypeValue)
client := &http.Client{}
resp, err = client.Do(req)
if err != nil {
return nil, errors.Wrap(err, "failure to speak HTTP / network connectivity problem")
}
if resp.StatusCode != http.StatusOK {
defer resp.Body.Close()
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, errors.Wrap(err, "cannot read body")
}
return nil, errors.Wrap(errors.New(string(b)), resp.Status)
}
return resp, nil
}
// CGCRequestAndRead is wrapper around CGCRequest.
// Read the response body until EOF.
func CGCRequestAndRead(method string, url string, body io.Reader) (respBody []byte, err error) {
resp, err := CGCRequest(method, url, body)
if err != nil {
return nil, err
}
defer resp.Body.Close()
respBody, err = ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
return respBody, nil
}
// CGCRequestAndReadTotalOffset is wrapper around CGCRequest.
// Read the response body until EOF.
// Returns X-Total-Matching-Query header value.
func CGCRequestAndReadTotalOffset(method string, url string, body io.Reader) (bytesResp []byte, totalOffset int, err error) {
resp, err := CGCRequest(method, url, body)
if err != nil {
return nil, 0, err
}
defer resp.Body.Close()
totalOffset, err = strconv.Atoi(resp.Header.Get(headerMaxOffset))
if err != nil {
return nil, 0, errors.Wrap(err, fmt.Sprintf("%s header missing", headerMaxOffset))
}
respBody, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, 0, err
}
return respBody, totalOffset, nil
}