Update oauth errors to use api errors

Signed-off-by: Derek McGowan <derek@mcgstyle.net> (github: dmcgowan)
This commit is contained in:
Derek McGowan 2016-11-09 19:29:18 -08:00
parent 16396a7a80
commit 051801f1d0
No known key found for this signature in database
GPG key ID: F58C5D0A4405ACDB

View file

@ -38,25 +38,6 @@ func (e *UnexpectedHTTPResponseError) Error() string {
return fmt.Sprintf("error parsing HTTP %d response body: %s: %q", e.StatusCode, e.ParseErr.Error(), string(e.Response)) return fmt.Sprintf("error parsing HTTP %d response body: %s: %q", e.StatusCode, e.ParseErr.Error(), string(e.Response))
} }
// OAuthError is returned when the request could not be authorized
// using the provided oauth token. This could represent a lack of
// permission or invalid token given from a token server.
// See https://tools.ietf.org/html/rfc6750#section-3
type OAuthError struct {
// ErrorCode is a code defined in https://tools.ietf.org/html/rfc6750#section-3.1
ErrorCode string
// Description is the error description associated with the error code
Description string
}
func (e *OAuthError) Error() string {
if e.Description != "" {
return fmt.Sprintf("oauth error %q: %s", e.ErrorCode, e.Description)
}
return fmt.Sprintf("oauth error %q", e.ErrorCode)
}
func parseHTTPErrorResponse(statusCode int, r io.Reader) error { func parseHTTPErrorResponse(statusCode int, r io.Reader) error {
var errors errcode.Errors var errors errcode.Errors
body, err := ioutil.ReadAll(r) body, err := ioutil.ReadAll(r)
@ -102,6 +83,17 @@ func parseHTTPErrorResponse(statusCode int, r io.Reader) error {
return errors return errors
} }
func makeErrorList(err error) []error {
if errL, ok := err.(errcode.Errors); ok {
return []error(errL)
}
return []error{err}
}
func mergeErrors(err1, err2 error) error {
return errcode.Errors(append(makeErrorList(err1), makeErrorList(err2)...))
}
// HandleErrorResponse returns error parsed from HTTP response for an // HandleErrorResponse returns error parsed from HTTP response for an
// unsuccessful HTTP response code (in the range 400 - 499 inclusive). An // unsuccessful HTTP response code (in the range 400 - 499 inclusive). An
// UnexpectedHTTPStatusError returned for response code outside of expected // UnexpectedHTTPStatusError returned for response code outside of expected
@ -109,15 +101,26 @@ func parseHTTPErrorResponse(statusCode int, r io.Reader) error {
func HandleErrorResponse(resp *http.Response) error { func HandleErrorResponse(resp *http.Response) error {
if resp.StatusCode >= 400 && resp.StatusCode < 500 { if resp.StatusCode >= 400 && resp.StatusCode < 500 {
// Check for OAuth errors within the `WWW-Authenticate` header first // Check for OAuth errors within the `WWW-Authenticate` header first
// See https://tools.ietf.org/html/rfc6750#section-3
for _, c := range challenge.ResponseChallenges(resp) { for _, c := range challenge.ResponseChallenges(resp) {
if c.Scheme == "bearer" { if c.Scheme == "bearer" {
errStr := c.Parameters["error"] var err errcode.Error
if errStr != "" { // codes defined at https://tools.ietf.org/html/rfc6750#section-3.1
return &OAuthError{ switch c.Parameters["error"] {
ErrorCode: errStr, case "invalid_token":
Description: c.Parameters["error_description"], err.Code = errcode.ErrorCodeUnauthorized
} case "insufficient_scope":
err.Code = errcode.ErrorCodeDenied
default:
continue
} }
if description := c.Parameters["error_description"]; description != "" {
err.Message = description
} else {
err.Message = err.Code.Message()
}
return mergeErrors(err, parseHTTPErrorResponse(resp.StatusCode, resp.Body))
} }
} }
err := parseHTTPErrorResponse(resp.StatusCode, resp.Body) err := parseHTTPErrorResponse(resp.StatusCode, resp.Body)