-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy patherror.go
More file actions
175 lines (149 loc) · 4.42 KB
/
error.go
File metadata and controls
175 lines (149 loc) · 4.42 KB
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
package httpx
import (
"errors"
"net/http"
"strings"
)
// StatusError represents an error that carries an HTTP status code.
// This interface allows errors to be categorized by their HTTP semantics.
type StatusError interface {
error
// GetStatus returns the HTTP status code associated with this error.
GetStatus() int32
}
// CodeError represents an error that carries a custom error code.
// This is useful for application-specific error classification beyond HTTP status.
type CodeError interface {
error
// GetCode returns the custom error code associated with this error.
GetCode() int32
}
// MessageError represents an error that carries a user-friendly message.
// This allows separation between technical error details and user-facing messages.
type MessageError interface {
error
// GetMessage returns the user-friendly message associated with this error.
GetMessage() string
}
// Error is a comprehensive error type that includes HTTP status, custom code, and user message.
type Error interface {
error
StatusError
CodeError
MessageError
}
// httpError is an unexported concrete implementation of Error.
// Keeping it unexported prevents external code from depending on the
// concrete type, preserving flexibility to change internals.
type httpError struct {
error
status int32
code int32
message string
}
func (e *httpError) GetStatus() int32 {
return e.status
}
func (e *httpError) GetCode() int32 {
return e.code
}
func (e *httpError) GetMessage() string {
return e.message
}
func (e *httpError) Error() string {
return e.error.Error()
}
func (e *httpError) Unwrap() error {
return e.error
}
// NewError creates a new error with HTTP status, custom code, and user message.
// It returns the broader Error interface to avoid exposing the concrete type
// and keep the API surface stable. If err is nil, a default HTTP error based on the
// status is used.
func NewError(status, code int32, message string, err error) Error {
if err == nil {
err = httpStatusError(status)
}
return &httpError{
error: err,
status: status,
code: code,
message: message,
}
}
func WithStatus(status int32, err error, messages ...string) Error {
code := int32(0)
var se CodeError
if errors.As(err, &se) {
code = se.GetCode()
}
return NewError(status, code, strings.Join(messages, "; "), err)
}
func NewWithStatus(status int32, message string) Error {
return WithStatus(status, errors.New(message))
}
func BadRequestError(err error, messages ...string) Error {
return WithStatus(http.StatusBadRequest, err, messages...)
}
func NewBadRequestError(message string) Error {
return WithStatus(http.StatusBadRequest, errors.New(message))
}
func UnauthorizedError(err error, messages ...string) Error {
return WithStatus(http.StatusUnauthorized, err, messages...)
}
func NewUnauthorizedError(message string) Error {
return WithStatus(http.StatusUnauthorized, errors.New(message))
}
func ForbiddenError(err error, messages ...string) Error {
return WithStatus(http.StatusForbidden, err, messages...)
}
func NewForbiddenError(message string) Error {
return WithStatus(http.StatusForbidden, errors.New(message))
}
func NotFoundError(err error, messages ...string) Error {
return WithStatus(http.StatusNotFound, err, messages...)
}
func NewNotFoundError(message string) Error {
return WithStatus(http.StatusNotFound, errors.New(message))
}
func InternalServerError(err error, messages ...string) Error {
return WithStatus(http.StatusInternalServerError, err, messages...)
}
func NewInternalServerError(message string) Error {
return WithStatus(http.StatusInternalServerError, errors.New(message))
}
func httpStatusError(status int32) error {
msg := http.StatusText(int(status))
if msg == "" {
msg = "Unknown error"
}
return errors.New(msg)
}
// ParseError extracts error information from various error types.
// It recognizes StatusError, CodeError, and MessageError interfaces and falls back
// to defaults for unknown error types.
func ParseError(err error) (code int32, status int32, message string) {
var he Error
if errors.As(err, &he) {
return he.GetCode(), he.GetStatus(), he.GetMessage()
}
var se StatusError
if errors.As(err, &se) {
status = se.GetStatus()
} else {
status = http.StatusInternalServerError
}
var ce CodeError
if errors.As(err, &ce) {
code = ce.GetCode()
} else {
code = status
}
var me MessageError
if errors.As(err, &me) {
message = me.GetMessage()
} else {
message = err.Error()
}
return
}