error.go 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. package client
  2. import (
  3. "encoding/json"
  4. "io"
  5. "net/http"
  6. "strings"
  7. )
  8. // APIError errors that may return from the Client.
  9. type APIError struct {
  10. Response *http.Response
  11. Body json.RawMessage // may be any []byte, response body is closed at this point.
  12. }
  13. // Error implements the standard error type.
  14. func (e APIError) Error() string {
  15. var b strings.Builder
  16. if e.Response != nil {
  17. b.WriteString(e.Response.Request.URL.String())
  18. b.WriteByte(':')
  19. b.WriteByte(' ')
  20. b.WriteString(http.StatusText(e.Response.StatusCode))
  21. b.WriteByte(' ')
  22. b.WriteByte('(')
  23. b.WriteString(e.Response.Status)
  24. b.WriteByte(')')
  25. if len(e.Body) > 0 {
  26. b.WriteByte(':')
  27. b.WriteByte(' ')
  28. b.Write(e.Body)
  29. }
  30. }
  31. return b.String()
  32. }
  33. // ExtractError returns the response wrapped inside an APIError.
  34. func ExtractError(resp *http.Response) APIError {
  35. body, _ := io.ReadAll(resp.Body)
  36. return APIError{
  37. Response: resp,
  38. Body: body,
  39. }
  40. }
  41. // GetError reports whether the given "err" is an APIError.
  42. func GetError(err error) (APIError, bool) {
  43. if err == nil {
  44. return APIError{}, false
  45. }
  46. apiErr, ok := err.(APIError)
  47. if !ok {
  48. return APIError{}, false
  49. }
  50. return apiErr, true
  51. }
  52. // DecodeError binds a json error to the "destPtr".
  53. func DecodeError(err error, destPtr interface{}) error {
  54. apiErr, ok := GetError(err)
  55. if !ok {
  56. return err
  57. }
  58. return json.Unmarshal(apiErr.Body, destPtr)
  59. }
  60. // GetErrorCode reads an error, which should be a type of APIError,
  61. // and returns its status code.
  62. // If the given "err" is nil or is not an APIError it returns 200,
  63. // acting as we have no error.
  64. func GetErrorCode(err error) int {
  65. apiErr, ok := GetError(err)
  66. if !ok {
  67. return http.StatusOK
  68. }
  69. return apiErr.Response.StatusCode
  70. }