1 package autorest 2 3 // Copyright 2017 Microsoft Corporation 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 17 import ( 18 "fmt" 19 "net/http" 20 ) 21 22 const ( 23 // UndefinedStatusCode is used when HTTP status code is not available for an error. 24 UndefinedStatusCode = 0 25 ) 26 27 // DetailedError encloses a error with details of the package, method, and associated HTTP 28 // status code (if any). 29 type DetailedError struct { 30 Original error 31 32 // PackageType is the package type of the object emitting the error. For types, the value 33 // matches that produced the the '%T' format specifier of the fmt package. For other elements, 34 // such as functions, it is just the package name (e.g., "autorest"). 35 PackageType string 36 37 // Method is the name of the method raising the error. 38 Method string 39 40 // StatusCode is the HTTP Response StatusCode (if non-zero) that led to the error. 41 StatusCode interface{} 42 43 // Message is the error message. 44 Message string 45 46 // Service Error is the response body of failed API in bytes 47 ServiceError []byte 48 49 // Response is the response object that was returned during failure if applicable. 50 Response *http.Response 51 } 52 53 // NewError creates a new Error conforming object from the passed packageType, method, and 54 // message. message is treated as a format string to which the optional args apply. 55 func NewError(packageType string, method string, message string, args ...interface{}) DetailedError { 56 return NewErrorWithError(nil, packageType, method, nil, message, args...) 57 } 58 59 // NewErrorWithResponse creates a new Error conforming object from the passed 60 // packageType, method, statusCode of the given resp (UndefinedStatusCode if 61 // resp is nil), and message. message is treated as a format string to which the 62 // optional args apply. 63 func NewErrorWithResponse(packageType string, method string, resp *http.Response, message string, args ...interface{}) DetailedError { 64 return NewErrorWithError(nil, packageType, method, resp, message, args...) 65 } 66 67 // NewErrorWithError creates a new Error conforming object from the 68 // passed packageType, method, statusCode of the given resp (UndefinedStatusCode 69 // if resp is nil), message, and original error. message is treated as a format 70 // string to which the optional args apply. 71 func NewErrorWithError(original error, packageType string, method string, resp *http.Response, message string, args ...interface{}) DetailedError { 72 if v, ok := original.(DetailedError); ok { 73 return v 74 } 75 76 statusCode := UndefinedStatusCode 77 if resp != nil { 78 statusCode = resp.StatusCode 79 } 80 81 return DetailedError{ 82 Original: original, 83 PackageType: packageType, 84 Method: method, 85 StatusCode: statusCode, 86 Message: fmt.Sprintf(message, args...), 87 Response: resp, 88 } 89 } 90 91 // Error returns a formatted containing all available details (i.e., PackageType, Method, 92 // StatusCode, Message, and original error (if any)). 93 func (e DetailedError) Error() string { 94 if e.Original == nil { 95 return fmt.Sprintf("%s#%s: %s: StatusCode=%d", e.PackageType, e.Method, e.Message, e.StatusCode) 96 } 97 return fmt.Sprintf("%s#%s: %s: StatusCode=%d -- Original Error: %v", e.PackageType, e.Method, e.Message, e.StatusCode, e.Original) 98 } 99 100 // Unwrap returns the original error. 101 func (e DetailedError) Unwrap() error { 102 return e.Original 103 } 104