forked from oVirt/go-ovirt
-
Notifications
You must be signed in to change notification settings - Fork 0
/
error.go
141 lines (128 loc) · 3.22 KB
/
error.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package ovirtsdk
import (
"bytes"
"errors"
"fmt"
"io/ioutil"
"net/http"
)
type baseError struct {
Code int
Msg string
}
func (b *baseError) Error() string {
return b.Msg
}
// AuthError indicates that an authentiation or authorization
// problem happened, like incorrect user name, incorrect password, or
// missing permissions.
type AuthError struct {
baseError
}
// NotFoundError indicates that an object can't be found.
type NotFoundError struct {
baseError
}
// CheckFault procoesses error parsing and returns it back
func CheckFault(response *http.Response) error {
resBytes, err := ioutil.ReadAll(response.Body)
if err != nil {
return fmt.Errorf("failed to read response (%w)", err)
}
// Process empty response body
if len(resBytes) == 0 {
return BuildError(response, nil)
}
reader := NewXMLReader(resBytes)
fault, err := XMLFaultReadOne(reader, nil, "")
if err != nil {
// If the XML is not a <fault>, just return nil
if err, ok := err.(XMLTagNotMatchError); ok {
return err
}
return err
}
if fault != nil || response.StatusCode >= 400 {
return BuildError(response, fault)
}
return errors.New("unknown error")
}
// CheckAction checks if response contains an Action instance
func CheckAction(response *http.Response) (*Action, error) {
resBytes, err := ioutil.ReadAll(response.Body)
if err != nil {
return nil, fmt.Errorf("failed to read response (%w)", err)
}
// Process empty response body
if len(resBytes) == 0 {
return nil, BuildError(response, nil)
}
faultreader := NewXMLReader(resBytes)
fault, err := XMLFaultReadOne(faultreader, nil, "")
if err != nil {
// If the tag mismatches, return the err
if _, ok := err.(XMLTagNotMatchError); !ok {
return nil, err
}
}
if fault != nil {
return nil, BuildError(response, fault)
}
actionreader := NewXMLReader(resBytes)
action, err := XMLActionReadOne(actionreader, nil, "")
if err != nil {
// If the tag mismatches, return the err
if _, ok := err.(XMLTagNotMatchError); !ok {
return nil, err
}
}
if action != nil {
if afault, ok := action.Fault(); ok {
return nil, BuildError(response, afault)
}
return action, nil
}
return nil, nil
}
// BuildError constructs error
func BuildError(response *http.Response, fault *Fault) error {
var buffer bytes.Buffer
if fault != nil {
if reason, ok := fault.Reason(); ok {
if buffer.Len() > 0 {
buffer.WriteString(" ")
}
buffer.WriteString(fmt.Sprintf("Fault reason is \"%s\".", reason))
}
if detail, ok := fault.Detail(); ok {
if buffer.Len() > 0 {
buffer.WriteString(" ")
}
buffer.WriteString(fmt.Sprintf("Fault detail is \"%s\".", detail))
}
}
if response != nil {
if buffer.Len() > 0 {
buffer.WriteString(" ")
}
buffer.WriteString(fmt.Sprintf("HTTP response code is \"%d\".", response.StatusCode))
buffer.WriteString(" ")
buffer.WriteString(fmt.Sprintf("HTTP response message is \"%s\".", response.Status))
if Contains(response.StatusCode, []int{401, 403}) {
return &AuthError{
baseError{
response.StatusCode,
buffer.String(),
},
}
} else if response.StatusCode == 404 {
return &NotFoundError{
baseError{
response.StatusCode,
buffer.String(),
},
}
}
}
return errors.New(buffer.String())
}