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