diff options
Diffstat (limited to 'internal/github/rest_client.go')
-rw-r--r-- | internal/github/rest_client.go | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/internal/github/rest_client.go b/internal/github/rest_client.go new file mode 100644 index 0000000..6fdd31c --- /dev/null +++ b/internal/github/rest_client.go @@ -0,0 +1,115 @@ +package github + +import ( + "bytes" + "encoding/json" + "fmt" + "net/http" +) + +type HTTPRequester interface { + Do(req *http.Request) (*http.Response, error) +} + +type BearerAuthClient struct { + HTTPRequester + Username string + Password string +} + +func WithBearerAuth( + cli HTTPRequester, + username, password string, +) *BearerAuthClient { + return &BearerAuthClient{cli, username, password} +} + +func (s *BearerAuthClient) Do(req *http.Request) (*http.Response, error) { + if s.Username != "" && s.Password != "" { + value := fmt.Sprintf("Bearer %s:%s", s.Username, s.Password) + req.Header.Set("Authorization", value) + } + return s.HTTPRequester.Do(req) +} + +type jsonClient struct { + Client HTTPRequester + basePath string +} + +func newJSONClient( + cli HTTPRequester, + basePath string, +) *jsonClient { + return &jsonClient{ + Client: cli, + basePath: basePath, + } +} + +func newHTTPJSONReq( + method string, + url string, + req interface{}, +) (*http.Request, error) { + body := &bytes.Buffer{} + if req != nil { + buf, err := json.Marshal(req) + if err != nil { + return nil, err + } + body = bytes.NewBuffer(buf) + } + httpReq, err := http.NewRequest(method, url, body) + if err != nil { + return nil, err + } + httpReq.Header.Set("Content-Type", "application/json") + httpReq.Header.Set("Accept", "application/json") + return httpReq, nil +} + +func decodeJSONResponse(httpResp *http.Response, resp interface{}) error { + if httpResp.StatusCode/100 != 2 { + return fmt.Errorf( + "received HTTP status code %d (%s)", + httpResp.StatusCode, + httpResp.Status, + ) + } + if resp == nil { + return nil + } + err := json.NewDecoder(httpResp.Body).Decode(resp) + if err != nil { + return err + } + return err +} + +func (s *jsonClient) Request( + method string, + statusCode *int, + path string, + req, resp interface{}, +) (int, error) { + url := fmt.Sprintf("%s/%s", s.basePath, path) + httpReq, err := newHTTPJSONReq(method, url, req) + if err != nil { + return 0, err + } + httpResp, err := s.Client.Do(httpReq) + if err != nil { + return 0, err + } + defer httpResp.Body.Close() + + err = decodeJSONResponse(httpResp, resp) + if err != nil { + return httpResp.StatusCode, err + } + if statusCode != nil && httpResp.StatusCode != *statusCode { + return httpResp.StatusCode, fmt.Errorf("expected status code %d but got %d", *statusCode, httpResp.StatusCode) + } + return httpResp.StatusCode, nil +} |