-
Notifications
You must be signed in to change notification settings - Fork 0
/
error.go
130 lines (109 loc) · 2.89 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
package go_nats
import (
"fmt"
"github.com/nats-io/nats.go"
"github.com/nats-io/nats.go/micro"
"github.com/pkg/errors"
)
// Predefined Errors
var (
ErrMarshallingFailed = errors.New("Failed to marshal proto message")
ErrUnmarshallingFailed = errors.New("Failed to unmarshal proto message")
)
// ServiceError is returned when the server returns an error instead of the expected message.
type ServiceError struct {
Code, Description, Details string
}
func (e ServiceError) Error() string {
if e.Details == "" {
return fmt.Sprintf("%s: %s", e.Code, e.Description)
}
return fmt.Sprintf("%s: %s (%s)", e.Code, e.Description, e.Details)
}
func (e ServiceError) Is(target error) bool {
var se ServiceError
ok := errors.As(target, &se)
return ok
}
func IsServiceError(err error) bool {
var se ServiceError
ok := errors.As(err, &se)
return ok
}
func AsServiceError(err error) (ServiceError, bool) {
var se ServiceError
ok := errors.As(err, &se)
return se, ok
}
// ServerError is a custom error type that can be used to return
// a statuscode along with an error description and additional to the client.
type ServerError struct {
Code, Description string
Wrapped error
Headers map[string][]string
}
func (n ServerError) Error() string {
if n.Wrapped != nil {
return n.Description + ": " + n.Wrapped.Error()
}
return n.Description
}
func (n ServerError) Cause() error {
return n.Wrapped
}
// GetWrapped returns the wrapped error as a byte slice, or nil if there is no wrapped error.
// It's therefore safe to be used directly in a NATS response, for example, like this:
// ```request.Error(natsErr.code, natsErr.description, natsErr.GetWrapped())```
func (n ServerError) GetWrapped() []byte {
if n.Wrapped != nil {
return []byte(n.Wrapped.Error())
}
return nil
}
func (n ServerError) ensureHeader() {
if n.Headers == nil {
n.Headers = make(nats.Header)
}
}
func (n ServerError) GetOptHeaders() micro.RespondOpt {
if n.Headers == nil || len(n.Headers) == 0 {
return func(m *nats.Msg) {}
}
return func(m *nats.Msg) {
if m.Header == nil {
m.Header = n.Headers
return
}
for k, v := range n.Headers {
m.Header[k] = v
}
}
}
func (n ServerError) AddHeader(header, value string) ServerError {
n.ensureHeader()
n.Headers[header] = append(n.Headers[header], value)
return n
}
func (n ServerError) SetHeader(header, value string) ServerError {
n.ensureHeader()
n.Headers[header] = []string{value}
return n
}
func (n ServerError) GetHeaders() micro.Headers {
n.ensureHeader()
return n.Headers
}
func (n ServerError) WithHeaders(headers map[string][]string) error {
n.Headers = headers
return n
}
func NewServerErr(code, description string) ServerError {
return WrapServerErr(nil, code, description)
}
func WrapServerErr(err error, code, description string) ServerError {
return ServerError{
Code: code,
Description: description,
Wrapped: err,
}
}