github.com/ablease/cli@v6.37.1-0.20180613014814-3adbb7d7fb19+incompatible/api/cloudcontroller/ccv2/errors.go (about) 1 package ccv2 2 3 import ( 4 "encoding/json" 5 "net/http" 6 7 "code.cloudfoundry.org/cli/api/cloudcontroller" 8 "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" 9 ) 10 11 // errorWrapper is the wrapper that converts responses with 4xx and 5xx status 12 // codes to an error. 13 type errorWrapper struct { 14 connection cloudcontroller.Connection 15 } 16 17 func newErrorWrapper() *errorWrapper { 18 return new(errorWrapper) 19 } 20 21 // Make converts RawHTTPStatusError, which represents responses with 4xx and 22 // 5xx status codes, to specific errors. 23 func (e *errorWrapper) Make(request *cloudcontroller.Request, passedResponse *cloudcontroller.Response) error { 24 err := e.connection.Make(request, passedResponse) 25 26 if rawHTTPStatusErr, ok := err.(ccerror.RawHTTPStatusError); ok { 27 if passedResponse.HTTPResponse.StatusCode >= http.StatusInternalServerError { 28 return convert500(rawHTTPStatusErr) 29 } 30 31 return convert400(rawHTTPStatusErr) 32 } 33 return err 34 } 35 36 // Wrap wraps a Cloud Controller connection in this error handling wrapper. 37 func (e *errorWrapper) Wrap(innerconnection cloudcontroller.Connection) cloudcontroller.Connection { 38 e.connection = innerconnection 39 return e 40 } 41 42 func convert400(rawHTTPStatusErr ccerror.RawHTTPStatusError) error { 43 // Try to unmarshal the raw error into a CC error. If unmarshaling fails, 44 // either we're not talking to a CC, or the CC returned invalid json. 45 var errorResponse ccerror.V2ErrorResponse 46 err := json.Unmarshal(rawHTTPStatusErr.RawResponse, &errorResponse) 47 if err != nil { 48 // ccv2/info.go converts this error to an APINotFoundError. 49 return ccerror.UnknownHTTPSourceError{StatusCode: rawHTTPStatusErr.StatusCode, RawResponse: rawHTTPStatusErr.RawResponse} 50 } 51 52 switch rawHTTPStatusErr.StatusCode { 53 case http.StatusBadRequest: // 400 54 return handleBadRequest(errorResponse) 55 case http.StatusUnauthorized: // 401 56 return handleUnauthorized(errorResponse) 57 case http.StatusForbidden: // 403 58 return ccerror.ForbiddenError{Message: errorResponse.Description} 59 case http.StatusNotFound: // 404 60 return ccerror.ResourceNotFoundError{Message: errorResponse.Description} 61 case http.StatusUnprocessableEntity: // 422 62 return ccerror.UnprocessableEntityError{Message: errorResponse.Description} 63 default: 64 return ccerror.V2UnexpectedResponseError{ 65 RequestIDs: rawHTTPStatusErr.RequestIDs, 66 ResponseCode: rawHTTPStatusErr.StatusCode, 67 V2ErrorResponse: errorResponse, 68 } 69 } 70 } 71 72 func convert500(rawHTTPStatusErr ccerror.RawHTTPStatusError) error { 73 return ccerror.V2UnexpectedResponseError{ 74 ResponseCode: rawHTTPStatusErr.StatusCode, 75 RequestIDs: rawHTTPStatusErr.RequestIDs, 76 V2ErrorResponse: ccerror.V2ErrorResponse{ 77 Description: string(rawHTTPStatusErr.RawResponse), 78 }, 79 } 80 } 81 82 func handleBadRequest(errorResponse ccerror.V2ErrorResponse) error { 83 switch errorResponse.ErrorCode { 84 case "CF-AppStoppedStatsError": 85 return ccerror.ApplicationStoppedStatsError{Message: errorResponse.Description} 86 case "CF-InstancesError": 87 return ccerror.InstancesError{Message: errorResponse.Description} 88 case "CF-InvalidRelation": 89 return ccerror.InvalidRelationError{Message: errorResponse.Description} 90 case "CF-NotStaged": 91 return ccerror.NotStagedError{Message: errorResponse.Description} 92 case "CF-ServiceBindingAppServiceTaken": 93 return ccerror.ServiceBindingTakenError{Message: errorResponse.Description} 94 default: 95 return ccerror.BadRequestError{Message: errorResponse.Description} 96 } 97 } 98 99 func handleUnauthorized(errorResponse ccerror.V2ErrorResponse) error { 100 if errorResponse.ErrorCode == "CF-InvalidAuthToken" { 101 return ccerror.InvalidAuthTokenError{Message: errorResponse.Description} 102 } 103 104 return ccerror.UnauthorizedError{Message: errorResponse.Description} 105 }