github.com/cloudfoundry-attic/cli-with-i18n@v6.32.1-0.20171002233121-7401370d3b85+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 // Wrap wraps a Cloud Controller connection in this error handling wrapper. 22 func (e *errorWrapper) Wrap(innerconnection cloudcontroller.Connection) cloudcontroller.Connection { 23 e.connection = innerconnection 24 return e 25 } 26 27 // Make converts RawHTTPStatusError, which represents responses with 4xx and 28 // 5xx status codes, to specific errors. 29 func (e *errorWrapper) Make(request *cloudcontroller.Request, passedResponse *cloudcontroller.Response) error { 30 err := e.connection.Make(request, passedResponse) 31 32 if rawHTTPStatusErr, ok := err.(ccerror.RawHTTPStatusError); ok { 33 return convert(rawHTTPStatusErr) 34 } 35 return err 36 } 37 38 func convert(rawHTTPStatusErr ccerror.RawHTTPStatusError) error { 39 // Try to unmarshal the raw error into a CC error. If unmarshaling fails, 40 // return the raw error. 41 var errorResponse ccerror.V2ErrorResponse 42 err := json.Unmarshal(rawHTTPStatusErr.RawResponse, &errorResponse) 43 if err != nil { 44 if rawHTTPStatusErr.StatusCode == http.StatusNotFound { 45 return ccerror.NotFoundError{Message: string(rawHTTPStatusErr.RawResponse)} 46 } 47 return rawHTTPStatusErr 48 } 49 50 switch rawHTTPStatusErr.StatusCode { 51 case http.StatusBadRequest: // 400 52 return handleBadRequest(errorResponse) 53 case http.StatusUnauthorized: // 401 54 return handleUnauthorized(errorResponse) 55 case http.StatusForbidden: // 403 56 return ccerror.ForbiddenError{Message: errorResponse.Description} 57 case http.StatusNotFound: // 404 58 return ccerror.ResourceNotFoundError{Message: errorResponse.Description} 59 case http.StatusUnprocessableEntity: // 422 60 return ccerror.UnprocessableEntityError{Message: errorResponse.Description} 61 default: 62 return ccerror.V2UnexpectedResponseError{ 63 V2ErrorResponse: errorResponse, 64 RequestIDs: rawHTTPStatusErr.RequestIDs, 65 ResponseCode: rawHTTPStatusErr.StatusCode, 66 } 67 } 68 } 69 70 func handleBadRequest(errorResponse ccerror.V2ErrorResponse) error { 71 switch errorResponse.ErrorCode { 72 case "CF-AppStoppedStatsError": 73 return ccerror.ApplicationStoppedStatsError{Message: errorResponse.Description} 74 case "CF-InstancesError": 75 return ccerror.InstancesError{Message: errorResponse.Description} 76 case "CF-InvalidRelation": 77 return ccerror.InvalidRelationError{Message: errorResponse.Description} 78 case "CF-NotStaged": 79 return ccerror.NotStagedError{Message: errorResponse.Description} 80 case "CF-ServiceBindingAppServiceTaken": 81 return ccerror.ServiceBindingTakenError{Message: errorResponse.Description} 82 default: 83 return ccerror.BadRequestError{Message: errorResponse.Description} 84 } 85 } 86 87 func handleUnauthorized(errorResponse ccerror.V2ErrorResponse) error { 88 if errorResponse.ErrorCode == "CF-InvalidAuthToken" { 89 return ccerror.InvalidAuthTokenError{Message: errorResponse.Description} 90 } 91 92 return ccerror.UnauthorizedError{Message: errorResponse.Description} 93 }