1package 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 17import ( 18 "fmt" 19 "net/http" 20) 21 22const ( 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). 29type 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. 55func 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. 63func 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. 71func 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)). 93func (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