github.com/akamai/AkamaiOPEN-edgegrid-golang/v2@v2.17.0/pkg/botman/errors.go (about) 1 package botman 2 3 import ( 4 "encoding/json" 5 "errors" 6 "fmt" 7 "io/ioutil" 8 "net/http" 9 "strings" 10 ) 11 12 type ( 13 // Error is a botman error interface. 14 Error struct { 15 Type string `json:"type"` 16 Title string `json:"title"` 17 Detail string `json:"detail"` 18 Errors []Error `json:"errors,omitempty"` 19 StatusCode int `json:"status,omitempty"` 20 } 21 ) 22 23 func (b *botman) Error(r *http.Response) error { 24 var e Error 25 var body []byte 26 27 body, err := ioutil.ReadAll(r.Body) 28 if err != nil { 29 b.Log(r.Request.Context()).Errorf("reading error response body: %s", err) 30 e.StatusCode = r.StatusCode 31 e.Title = "Failed to read error body" 32 e.Detail = err.Error() 33 return &e 34 } 35 36 if err := json.Unmarshal(body, &e); err != nil { 37 b.Log(r.Request.Context()).Errorf("could not unmarshal API error: %s", err) 38 e.Title = "Failed to unmarshal error body" 39 e.Detail = err.Error() 40 } 41 42 e.StatusCode = r.StatusCode 43 44 return &e 45 } 46 47 // Error returns a string formatted using a given title, type, and detail information. 48 func (e *Error) Error() string { 49 detail := e.Detail 50 if e.Errors != nil && len(e.Errors) > 0 { 51 var childErrorDetails []string 52 for _, err := range e.Errors { 53 childErrorDetails = append(childErrorDetails, err.Detail) 54 } 55 detail += ": [" + strings.Join(childErrorDetails, ", ") + " ]" 56 } 57 return fmt.Sprintf("Title: %s; Type: %s; Detail: %s", e.Title, e.Type, detail) 58 } 59 60 // Is handles error comparisons. 61 func (e *Error) Is(target error) bool { 62 var t *Error 63 if !errors.As(target, &t) { 64 return false 65 } 66 67 if e == t { 68 return true 69 } 70 71 if e.StatusCode != t.StatusCode { 72 return false 73 } 74 75 return e.Error() == t.Error() 76 }