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