github.com/Files-com/files-sdk-go/v2@v2.1.2/responseerror.go (about)

     1  package files_sdk
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"io"
     7  	"net/http"
     8  	"strconv"
     9  	"time"
    10  
    11  	"github.com/Files-com/files-sdk-go/v2/lib"
    12  )
    13  
    14  type ResponseError struct {
    15  	Type         string          `json:"type"`
    16  	Title        string          `json:"title"`
    17  	ErrorMessage string          `json:"error"`
    18  	HttpCode     int             `json:"http-code"`
    19  	Errors       []ResponseError `json:"errors"`
    20  	Data         Data            `json:"data"`
    21  }
    22  
    23  const (
    24  	DestinationExists = "processing-failure/destination-exists"
    25  )
    26  
    27  func IsDestinationExistsError(err error) bool {
    28  	re, ok := err.(ResponseError)
    29  	return ok && re.Type == DestinationExists
    30  }
    31  
    32  type SignRequest struct {
    33  	Version   string `json:"version"`
    34  	KeyHandle string `json:"keyHandle"`
    35  }
    36  
    37  type U2fSignRequests struct {
    38  	AppId       string      `json:"app_id"`
    39  	Challenge   string      `json:"challenge"`
    40  	SignRequest SignRequest `json:"sign_request"`
    41  }
    42  
    43  type Data struct {
    44  	U2fSIgnRequests               []U2fSignRequests `json:"u2f_sign_requests,omitempty"`
    45  	PartialSessionId              string            `json:"partial_session_id,omitempty"`
    46  	TwoFactorAuthenticationMethod []string          `json:"two_factor_authentication_methods,omitempty"`
    47  	// Download Request Status
    48  	BytesTransferred int64     `json:"bytes_transferred"`
    49  	Status           string    `json:"status"`
    50  	StartedAt        time.Time `json:"started_at"`
    51  	CompletedAt      time.Time `json:"completed_at"`
    52  	TouchedAt        time.Time `json:"touched_at"`
    53  }
    54  
    55  func (e ResponseError) Error() string {
    56  	return fmt.Sprintf("%v - `%v`", e.Title, e.ErrorMessage)
    57  }
    58  
    59  func (e ResponseError) IsNil() bool {
    60  	return e.ErrorMessage == ""
    61  }
    62  
    63  func (e ResponseError) Is(err error) bool {
    64  	_, ok := err.(ResponseError)
    65  
    66  	return ok
    67  }
    68  
    69  func (e *ResponseError) UnmarshalJSON(data []byte) error {
    70  	type re ResponseError
    71  	var v re
    72  	err := json.Unmarshal(data, &v)
    73  
    74  	if err != nil {
    75  		jsonError, ok := err.(*json.UnmarshalTypeError)
    76  
    77  		if ok && jsonError.Field == "" {
    78  			if jsonError.Value == "string" {
    79  				var str string
    80  				json.Unmarshal(data, &str)
    81  				v.ErrorMessage = str
    82  			} else if jsonError.Value != "array" {
    83  				return err
    84  			}
    85  		} else if ok && jsonError.Field == "http-code" {
    86  			tmp := make(map[string]interface{})
    87  			json.Unmarshal(data, &tmp)
    88  			intVar, _ := strconv.Atoi(tmp["http-code"].(string))
    89  			v.HttpCode = intVar
    90  		} else {
    91  			return err
    92  		}
    93  
    94  		jsonSyntaxErr, ok := err.(*json.SyntaxError)
    95  		if ok && jsonSyntaxErr.Error() == "invalid character '<' looking for beginning of value" {
    96  			return fmt.Errorf(string(data))
    97  		}
    98  	}
    99  
   100  	*e = ResponseError(v)
   101  	return nil
   102  }
   103  
   104  func APIError(callbacks ...func(ResponseError) ResponseError) func(res *http.Response) error {
   105  	return func(res *http.Response) error {
   106  		if lib.IsNonOkStatus(res) && lib.IsHTML(res) && res.Header.Get("X-Request-Id") != "" && res.Header.Get("Server") == "nginx" {
   107  			return fmt.Errorf("files.com Server error - request id: %v", res.Header.Get("X-Request-Id"))
   108  		}
   109  
   110  		if lib.IsNonOkStatus(res) && lib.IsJSON(res) {
   111  			data, err := io.ReadAll(res.Body)
   112  			if err != nil {
   113  				return lib.NonOkError(res)
   114  			}
   115  
   116  			re := ResponseError{}
   117  
   118  			err = re.UnmarshalJSON(data)
   119  			if err != nil {
   120  				return lib.NonOkError(res)
   121  			}
   122  
   123  			if re.IsNil() {
   124  				return lib.NonOkError(res)
   125  			}
   126  			for _, callback := range callbacks {
   127  				re = callback(re)
   128  			}
   129  			return re
   130  		}
   131  		return nil
   132  	}
   133  }