2014-08-09 23:51:08 +00:00
|
|
|
package client
|
2014-07-16 07:34:23 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"encoding/json"
|
|
|
|
"errors"
|
|
|
|
"io/ioutil"
|
|
|
|
"net/http"
|
|
|
|
"net/url"
|
|
|
|
"strconv"
|
|
|
|
)
|
|
|
|
|
2014-08-09 23:51:08 +00:00
|
|
|
type Client struct {
|
|
|
|
token string
|
|
|
|
url string
|
|
|
|
|
|
|
|
Commits *CommitService
|
|
|
|
Repos *RepoService
|
|
|
|
Users *UserService
|
|
|
|
}
|
|
|
|
|
|
|
|
func New(token, url string) *Client {
|
|
|
|
c := Client{
|
|
|
|
token: token,
|
|
|
|
url: url,
|
|
|
|
}
|
|
|
|
|
|
|
|
c.Commits = &CommitService{&c}
|
|
|
|
c.Repos = &RepoService{&c}
|
|
|
|
c.Users = &UserService{&c}
|
|
|
|
return &c
|
|
|
|
}
|
|
|
|
|
2014-07-16 07:34:23 +00:00
|
|
|
var (
|
|
|
|
ErrNotFound = errors.New("Not Found")
|
|
|
|
ErrForbidden = errors.New("Forbidden")
|
|
|
|
ErrBadRequest = errors.New("Bad Request")
|
|
|
|
ErrNotAuthorized = errors.New("Unauthorized")
|
|
|
|
ErrInternalServer = errors.New("Internal Server Error")
|
|
|
|
)
|
|
|
|
|
2014-08-09 23:51:08 +00:00
|
|
|
// runs an http.Request and parses the JSON-encoded http.Response,
|
2014-07-16 07:34:23 +00:00
|
|
|
// storing the result in the value pointed to by v.
|
2014-08-09 23:51:08 +00:00
|
|
|
func (c *Client) run(method, path string, in, out interface{}) error {
|
2014-07-16 07:34:23 +00:00
|
|
|
|
|
|
|
// create the URI
|
2014-08-09 23:51:08 +00:00
|
|
|
uri, err := url.Parse(c.url + path)
|
2014-07-16 07:34:23 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(uri.Scheme) == 0 {
|
|
|
|
uri.Scheme = "http"
|
|
|
|
}
|
|
|
|
|
2014-08-09 23:51:08 +00:00
|
|
|
if len(c.token) > 0 {
|
2014-07-16 07:34:23 +00:00
|
|
|
params := uri.Query()
|
2014-08-09 23:51:08 +00:00
|
|
|
params.Add("access_token", c.token)
|
2014-07-16 07:34:23 +00:00
|
|
|
uri.RawQuery = params.Encode()
|
|
|
|
}
|
|
|
|
|
|
|
|
// create the request
|
|
|
|
req := &http.Request{
|
|
|
|
URL: uri,
|
|
|
|
Method: method,
|
|
|
|
ProtoMajor: 1,
|
|
|
|
ProtoMinor: 1,
|
|
|
|
Close: true,
|
|
|
|
ContentLength: 0,
|
|
|
|
}
|
|
|
|
|
|
|
|
// if data input is provided, serialize to JSON
|
|
|
|
if in != nil {
|
|
|
|
inJson, err := json.Marshal(in)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
buf := bytes.NewBuffer(inJson)
|
|
|
|
req.Body = ioutil.NopCloser(buf)
|
|
|
|
|
|
|
|
req.ContentLength = int64(len(inJson))
|
|
|
|
req.Header.Set("Content-Length", strconv.Itoa(len(inJson)))
|
|
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
}
|
|
|
|
|
|
|
|
// make the request using the default http client
|
|
|
|
resp, err := http.DefaultClient.Do(req)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Read the bytes from the body (make sure we defer close the body)
|
|
|
|
defer resp.Body.Close()
|
|
|
|
body, err := ioutil.ReadAll(resp.Body)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check for an http error status (ie not 200 StatusOK)
|
|
|
|
switch resp.StatusCode {
|
|
|
|
case 404:
|
|
|
|
return ErrNotFound
|
|
|
|
case 403:
|
|
|
|
return ErrForbidden
|
|
|
|
case 401:
|
|
|
|
return ErrNotAuthorized
|
|
|
|
case 400:
|
|
|
|
return ErrBadRequest
|
|
|
|
case 500:
|
|
|
|
return ErrInternalServer
|
|
|
|
}
|
|
|
|
|
|
|
|
// Unmarshall the JSON response
|
|
|
|
if out != nil {
|
|
|
|
return json.Unmarshal(body, out)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
2014-08-09 23:51:08 +00:00
|
|
|
|
|
|
|
// do makes an http.Request and returns the response
|
|
|
|
func (c *Client) do(method, path string) (*http.Response, error) {
|
|
|
|
|
|
|
|
// create the URI
|
|
|
|
uri, err := url.Parse(c.url + path)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(uri.Scheme) == 0 {
|
|
|
|
uri.Scheme = "http"
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(c.token) > 0 {
|
|
|
|
params := uri.Query()
|
|
|
|
params.Add("access_token", c.token)
|
|
|
|
uri.RawQuery = params.Encode()
|
|
|
|
}
|
|
|
|
|
|
|
|
// create the request
|
|
|
|
req := &http.Request{
|
|
|
|
URL: uri,
|
|
|
|
Method: method,
|
|
|
|
ProtoMajor: 1,
|
|
|
|
ProtoMinor: 1,
|
|
|
|
Close: true,
|
|
|
|
ContentLength: 0,
|
|
|
|
}
|
|
|
|
|
|
|
|
// make the request using the default http client
|
|
|
|
return http.DefaultClient.Do(req)
|
|
|
|
}
|