func (c *Client) stream(rawurl, method string, in, out interface{}) (io.ReadCloser, error) {
	uri, err := url.Parse(rawurl)
	if err != nil {
		return nil, err
	}
	var buf io.ReadWriter
	if in != nil {
		buf = new(bytes.Buffer)
		err := json.NewEncoder(buf).Encode(in)
		if err != nil {
			return nil, err
		}
	}
	req, err := http.NewRequest(method, uri.String(), buf)
	if err != nil {
		return nil, err
	}
	if in != nil {
		req.Header.Set("Content-Type", "application/json")
	}
	req.Header.Set("Accept", "application/vnd.github.loki-preview+json")
	resp, err := c.client.Do(req)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode > http.StatusPartialContent {
		defer resp.Body.Close()
		out, _ := ioutil.ReadAll(resp.Body)
		return nil, fmt.Errorf(string(out))
	}
	return resp.Body, nil
}
helper function to stream an http request
package github
import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"golang.org/x/oauth2"
)
const (
	pathLogin  = "%slogin?access_token=%s"
	pathUser   = "%sapi/user"
	pathRepos  = "%sapi/user/repos"
	pathRepo   = "%sapi/repos/%s"
	pathConf   = "%sapi/repos/%s/maintainers"
	pathBranch = "%srepos/%s/%s/branches/%s"
)
type Client struct {
	client *http.Client
	base   string  
}
func NewClient(uri string) *Client {
	return &Client{http.DefaultClient, uri}
}
func NewClientToken(uri, token string) *Client {
	config := new(oauth2.Config)
	auther := config.Client(oauth2.NoContext, &oauth2.Token{AccessToken: token})
	return &Client{auther, uri}
}
func (c *Client) SetClient(client *http.Client) {
	c.client = client
}
func (c *Client) Branch(owner, name, branch string) (*Branch, error) {
	out := new(Branch)
	uri := fmt.Sprintf(pathBranch, c.base, owner, name, branch)
	err := c.get(uri, out)
	return out, err
}
func (c *Client) BranchProtect(owner, name, branch string, in *Branch) error {
	uri := fmt.Sprintf(pathBranch, c.base, owner, name, branch)
	return c.patch(uri, in, nil)
}
func (c *Client) get(rawurl string, out interface{}) error {
	return c.do(rawurl, "GET", nil, out)
}
func (c *Client) post(rawurl string, in, out interface{}) error {
	return c.do(rawurl, "POST", in, out)
}
func (c *Client) put(rawurl string, in, out interface{}) error {
	return c.do(rawurl, "PUT", in, out)
}
func (c *Client) patch(rawurl string, in, out interface{}) error {
	return c.do(rawurl, "PATCH", in, out)
}
func (c *Client) delete(rawurl string) error {
	return c.do(rawurl, "DELETE", nil, nil)
}
func (c *Client) do(rawurl, method string, in, out interface{}) error {
	body, err := c.stream(rawurl, method, in, out)
	if err != nil {
		return err
	}
	defer body.Close()
	if out != nil {
		return json.NewDecoder(body).Decode(out)
	}
	return nil
}