This repository has been archived by the owner on Jul 12, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 7
/
client.go
152 lines (122 loc) · 4.43 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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
package octokit
import (
"io"
"net/http"
"net/url"
"github.com/jingweno/go-sawyer"
"github.com/jingweno/go-sawyer/hypermedia"
)
// NewClient creates a new Client using the given authorization method. Provides a
// very simple client for connecting to the GitHub API using Octokit.
func NewClient(authMethod AuthMethod) *Client {
return NewClientWith(gitHubAPIURL, userAgent, authMethod, nil)
}
// NewClientWith creates a new Client with a particular base URL which all requests will
// be appended onto - often the GitHub URL - the user agent being represented, the
// authentication method, and a pointer to a httpClient if a particular client is being
// wrapped. If httpClient is nil a default httpClient will be used.
func NewClientWith(baseURL string, userAgent string, authMethod AuthMethod, httpClient *http.Client) *Client {
client, _ := sawyer.NewFromString(baseURL, httpClient)
return &Client{Client: client, UserAgent: userAgent, AuthMethod: authMethod}
}
// Client wraps a sawyer Client, a higher level wrapper for HttpClient, with a particular
// represented user agent and authentication method for GitHub. Can also store the particular
// hypermedia relations accessible through the root address.
type Client struct {
*sawyer.Client
UserAgent string
AuthMethod AuthMethod
rootRels hypermedia.Relations
}
// NewRequest produces a simple request for the given url and applies the proper headers
// currently associated with the client to that request.
func (c *Client) NewRequest(urlStr string) (req *Request, err error) {
req, err = newRequest(c, urlStr)
if err != nil {
return
}
c.applyRequestHeaders(req)
return
}
// a GET request with specific media type set
func (c *Client) getBody(url *url.URL, mediaType string) (patch io.ReadCloser, result *Result) {
result = sendRequest(c, url, func(req *Request) (*Response, error) {
req.Header.Set("Accept", mediaType)
return req.Get(nil)
})
if result.Response != nil {
patch = result.Response.Body
}
return
}
func (c *Client) head(url *url.URL, output interface{}) (result *Result) {
return sendRequest(c, url, func(req *Request) (*Response, error) {
return req.Head(output)
})
}
func (c *Client) get(url *url.URL, output interface{}) (result *Result) {
return sendRequest(c, url, func(req *Request) (*Response, error) {
return req.Get(output)
})
}
func (c *Client) post(url *url.URL, input interface{}, output interface{}) (result *Result) {
return sendRequest(c, url, func(req *Request) (*Response, error) {
return req.Post(input, output)
})
}
func (c *Client) put(url *url.URL, input interface{}, output interface{}) (result *Result) {
return sendRequest(c, url, func(req *Request) (*Response, error) {
return req.Put(input, output)
})
}
func (c *Client) delete(url *url.URL, input interface{}, output interface{}) (result *Result) {
return sendRequest(c, url, func(req *Request) (*Response, error) {
return req.Delete(input, output)
})
}
func (c *Client) patch(url *url.URL, input interface{}, output interface{}) (result *Result) {
return sendRequest(c, url, func(req *Request) (*Response, error) {
return req.Patch(input, output)
})
}
func (c *Client) upload(uploadUrl *url.URL, asset io.ReadCloser, contentType string, contentLength int64) (result *Result) {
req, err := c.NewRequest(uploadUrl.String())
if err != nil {
result = newResult(nil, err)
return
}
req.Header.Set("Content-Type", contentType)
req.ContentLength = contentLength
req.Body = asset
sawyerResp := req.Request.Post()
resp, err := NewResponse(sawyerResp)
return newResult(resp, err)
}
func (c *Client) applyRequestHeaders(req *Request) {
req.Header.Set("Accept", defaultMediaType)
req.Header.Set("User-Agent", c.UserAgent)
if c.AuthMethod != nil {
req.Header.Set("Authorization", c.AuthMethod.String())
}
if basicAuth, ok := c.AuthMethod.(BasicAuth); ok && basicAuth.OneTimePassword != "" {
req.Header.Set("X-GitHub-OTP", basicAuth.OneTimePassword)
}
// Go doesn't apply `Host` on the header, instead it consults `Request.Host`
// Populate `Host` if it exists in `Client.Header`
// See Bug https://code.google.com/p/go/issues/detail?id=7682
host := c.Header.Get("Host")
if host != "" {
req.Request.Host = host
}
return
}
func sendRequest(c *Client, url *url.URL, fn func(r *Request) (*Response, error)) (result *Result) {
req, err := c.NewRequest(url.String())
if err != nil {
result = newResult(nil, err)
return
}
resp, err := fn(req)
result = newResult(resp, err)
return
}