-
Notifications
You must be signed in to change notification settings - Fork 0
/
errors.go
94 lines (81 loc) · 3.02 KB
/
errors.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
package ccv2
import (
"encoding/json"
"fmt"
"net/http"
"code.cloudfoundry.org/cli/api/cloudcontroller"
)
// CCErrorResponse represents a generic Cloud Controller V2 error response.
type CCErrorResponse struct {
Code int `json:"code"`
Description string `json:"description"`
ErrorCode string `json:"error_code"`
}
// UnexpectedResponseError is returned when the client gets an error that has
// not been accounted for.
type UnexpectedResponseError struct {
CCErrorResponse
RequestIDs []string
ResponseCode int
}
func (e UnexpectedResponseError) Error() string {
message := fmt.Sprintf("Unexpected Response\nResponse code: %d\nCC code: %d\nCC error code: %s", e.ResponseCode, e.Code, e.ErrorCode)
for _, id := range e.RequestIDs {
message = fmt.Sprintf("%s\nRequest ID: %s", message, id)
}
return fmt.Sprintf("%s\nDescription: %s", message, e.Description)
}
// errorWrapper is the wrapper that converts responses with 4xx and 5xx status
// codes to an error.
type errorWrapper struct {
connection cloudcontroller.Connection
}
func newErrorWrapper() *errorWrapper {
return new(errorWrapper)
}
// Wrap wraps a Cloud Controller connection in this error handling wrapper.
func (e *errorWrapper) Wrap(innerconnection cloudcontroller.Connection) cloudcontroller.Connection {
e.connection = innerconnection
return e
}
// Make converts RawHTTPStatusError, which represents responses with 4xx and
// 5xx status codes, to specific errors.
func (e *errorWrapper) Make(request *http.Request, passedResponse *cloudcontroller.Response) error {
err := e.connection.Make(request, passedResponse)
if rawHTTPStatusErr, ok := err.(cloudcontroller.RawHTTPStatusError); ok {
return convert(rawHTTPStatusErr)
}
return err
}
func convert(rawHTTPStatusErr cloudcontroller.RawHTTPStatusError) error {
// Try to unmarshal the raw error into a CC error. If unmarshaling fails,
// return the raw error.
var errorResponse CCErrorResponse
err := json.Unmarshal(rawHTTPStatusErr.RawResponse, &errorResponse)
if err != nil {
if rawHTTPStatusErr.StatusCode == http.StatusNotFound {
return cloudcontroller.NotFoundError{Message: string(rawHTTPStatusErr.RawResponse)}
}
return rawHTTPStatusErr
}
switch rawHTTPStatusErr.StatusCode {
case http.StatusUnauthorized: // 401
if errorResponse.ErrorCode == "CF-InvalidAuthToken" {
return cloudcontroller.InvalidAuthTokenError{Message: errorResponse.Description}
}
return cloudcontroller.UnauthorizedError{Message: errorResponse.Description}
case http.StatusForbidden: // 403
return cloudcontroller.ForbiddenError{Message: errorResponse.Description}
case http.StatusNotFound: // 404
return cloudcontroller.ResourceNotFoundError{Message: errorResponse.Description}
case http.StatusUnprocessableEntity: // 422
return cloudcontroller.UnprocessableEntityError{Message: errorResponse.Description}
default:
return UnexpectedResponseError{
CCErrorResponse: errorResponse,
RequestIDs: rawHTTPStatusErr.RequestIDs,
ResponseCode: rawHTTPStatusErr.StatusCode,
}
}
return nil
}