errors.go raw

   1  package bunny
   2  
   3  import (
   4  	"fmt"
   5  	"net/http"
   6  	"strings"
   7  )
   8  
   9  // HTTPError is returned by the Client when an unsuccessful HTTP response was
  10  // returned or a response could not be processed.
  11  // If the body of an unsuccessful HTTP response contains an APIError in the
  12  // body, APIError is returned by the Client instead.
  13  type HTTPError struct {
  14  	// RequestURL is the address to which the request was sent that caused the error.
  15  	RequestURL string
  16  	// The HTTP response status code.
  17  	StatusCode int
  18  	// The raw http response body. It's nil if the response had no body or it could not be received.
  19  	RespBody []byte
  20  	// Errors contain errors that happened while receiving or processing the HTTP response.
  21  	Errors []error
  22  }
  23  
  24  // Error returns a textual representation of the error.
  25  func (e *HTTPError) Error() string {
  26  	var res strings.Builder
  27  
  28  	res.WriteString(fmt.Sprintf("http-request to %s failed: %s (%d)",
  29  		e.RequestURL, http.StatusText(e.StatusCode), e.StatusCode,
  30  	))
  31  
  32  	if len(e.Errors) > 0 {
  33  		res.WriteString(", errors: " + strings.Join(errorsToStrings(e.Errors), ", "))
  34  	}
  35  
  36  	return res.String()
  37  }
  38  
  39  func errorsToStrings(errs []error) []string {
  40  	res := make([]string, 0, len(errs))
  41  
  42  	for _, err := range errs {
  43  		res = append(res, err.Error())
  44  	}
  45  
  46  	return res
  47  }
  48  
  49  // AuthenticationError represents an Unauthorized (401) HTTP error.
  50  type AuthenticationError struct {
  51  	Message string
  52  }
  53  
  54  // Error returns a textual representation of the error.
  55  func (e *AuthenticationError) Error() string {
  56  	return e.Message
  57  }
  58  
  59  // APIError represents an error that is returned by some Bunny API endpoints on
  60  // failures.
  61  type APIError struct {
  62  	HTTPError
  63  
  64  	ErrorKey string `json:"ErrorKey"`
  65  	Field    string `json:"Field"`
  66  	Message  string `json:"Message"`
  67  }
  68  
  69  // Error returns the string representation of the error.
  70  // ErrorKey, Field and Message are omitted if they are empty.
  71  func (e *APIError) Error() string {
  72  	var res strings.Builder
  73  
  74  	res.WriteString(e.HTTPError.Error())
  75  
  76  	if e.ErrorKey != "" {
  77  		res.WriteString(", ")
  78  		res.WriteString(e.ErrorKey)
  79  
  80  		if e.Field != "" {
  81  			res.WriteString(": ")
  82  			res.WriteString(e.Field)
  83  		}
  84  	} else if e.Field != "" {
  85  		res.WriteString(", ")
  86  		res.WriteString(e.Field)
  87  	}
  88  
  89  	if e.Message != "" {
  90  		// Field and ErrorKey contains the same information then Message, no need to log them.
  91  		res.WriteString(", ")
  92  		res.WriteString(e.Message)
  93  	}
  94  
  95  	return res.String()
  96  }
  97