...
1 package apperror
2
3 import (
4 "bytes"
5 "encoding/json"
6 "errors"
7 "fmt"
8 )
9
10 type StatusCoder interface {
11 error
12 Caller
13 StatusCode() int
14 }
15
16 type Caller interface {
17 SourceLocation() SourceLocation
18 }
19
20 type JSONResponder interface {
21 error
22 Caller
23 JSONResponse() (int, interface{})
24 JSONDetails() map[string]interface{}
25 }
26
27 type ErrorAborter interface {
28 error
29 Caller
30 AbortError() (int, error)
31 }
32
33 type Redirecter interface {
34 error
35 Redirect() (int, string, string)
36 }
37
38 type ErrorCoder interface {
39 ErrorCode() string
40 }
41
42
43 func ErrorChain(err error) string {
44 var buf bytes.Buffer
45
46 for err != nil {
47 switch e := err.(type) {
48 case *StatusError:
49 fmt.Fprintf(&buf, "[%v]: %s", e.code, e.Error())
50 case *JSONError:
51 fmt.Fprintf(&buf, "[%v]: %s", e.code, e.Error())
52 case *AbortError:
53 fmt.Fprintf(&buf, "[%v]: %s", e.code, e.Error())
54 case RedirectError:
55 code, loc, _ := e.Redirect()
56 fmt.Fprintf(&buf, "[%v]: redirect to: %s", code, loc)
57 default:
58
59 }
60
61 err = errors.Unwrap(err)
62 }
63
64 return buf.String()
65 }
66
67
68
69 func ErrorCode(err error) string {
70 if errCoder, ok := err.(ErrorCoder); ok {
71 return errCoder.ErrorCode()
72 }
73 return ""
74 }
75
76 type SourceLocation struct {
77 File string `json:"file,omitempty"`
78 Func string `json:"function,omitempty"`
79 Line int `json:"line,omitempty"`
80 }
81
82 func (sl SourceLocation) ToMap() map[string]interface{} {
83 res := make(map[string]interface{})
84
85 bytes, err := json.Marshal(sl)
86 if err != nil {
87 return nil
88 }
89
90 err = json.Unmarshal(bytes, &res)
91 if err != nil {
92 return nil
93 }
94
95 return res
96 }
97
View as plain text