github.com/bytom/bytom@v1.1.2-0.20221014091027-bbcba3df6075/net/http/httperror/httperror.go (about) 1 // Package httperror defines the format for HTTP error responses 2 // from Chain services. 3 package httperror 4 5 import ( 6 "context" 7 "net/http" 8 9 "github.com/bytom/bytom/errors" 10 "github.com/bytom/bytom/net/http/httpjson" 11 ) 12 13 // Info contains a set of error codes to send to the user. 14 type Info struct { 15 HTTPStatus int `json:"-"` 16 ChainCode string `json:"code"` 17 Message string `json:"msg"` 18 } 19 20 // Response defines the error response for a Chain error. 21 type Response struct { 22 Info 23 Status string `json:"status,omitempty"` 24 Detail string `json:"detail,omitempty"` 25 Data map[string]interface{} `json:"data,omitempty"` 26 Temporary bool `json:"temporary"` 27 } 28 29 // Formatter defines rules for mapping errors to the Chain error 30 // response format. 31 type Formatter struct { 32 Default Info 33 IsTemporary func(info Info, err error) bool 34 Errors map[error]Info 35 } 36 37 // Format builds an error Response body describing err by consulting 38 // the f.Errors lookup table. If no entry is found, it returns f.Default. 39 func (f Formatter) Format(err error) (body Response) { 40 root := errors.Root(err) 41 // Some types cannot be used as map keys, for example slices. 42 // If an error's underlying type is one of these, don't panic. 43 // Just treat it like any other missing entry. 44 defer func() { 45 if err := recover(); err != nil { 46 body = Response{f.Default, "fail", "", nil, true} 47 } 48 }() 49 info, ok := f.Errors[root] 50 if !ok { 51 info = f.Default 52 } 53 54 body = Response{ 55 Info: info, 56 Status: "fail", 57 Detail: errors.Detail(err), 58 Data: errors.Data(err), 59 Temporary: f.IsTemporary(info, err), 60 } 61 return body 62 } 63 64 // Write writes a json encoded Response to the ResponseWriter. 65 // It uses the status code associated with the error. 66 // 67 // Write may be used as an ErrorWriter in the httpjson package. 68 func (f Formatter) Write(ctx context.Context, w http.ResponseWriter, err error) { 69 resp := f.Format(err) 70 httpjson.Write(ctx, w, resp.HTTPStatus, resp) 71 }