50 lines
1.2 KiB
Go
50 lines
1.2 KiB
Go
package client
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"strings"
|
|
)
|
|
|
|
// APIError is returned for every non-2xx API response. Validation contains
|
|
// field-specific messages for 422 responses; Message contains ordinary API
|
|
// error strings.
|
|
type APIError struct {
|
|
StatusCode int
|
|
Message string
|
|
Validation map[string]string
|
|
Body string
|
|
}
|
|
|
|
// Error implements error using the API message or HTTP status.
|
|
func (e *APIError) Error() string {
|
|
switch {
|
|
case e.Message != "":
|
|
return fmt.Sprintf("gardomatic API: %s (%d)", e.Message, e.StatusCode)
|
|
case len(e.Validation) != 0:
|
|
return fmt.Sprintf("gardomatic API: validation failed (%d)", e.StatusCode)
|
|
default:
|
|
return fmt.Sprintf("gardomatic API: request failed (%d)", e.StatusCode)
|
|
}
|
|
}
|
|
|
|
func newAPIError(response *http.Response, body []byte) *APIError {
|
|
apiError := &APIError{
|
|
StatusCode: response.StatusCode,
|
|
Body: strings.TrimSpace(string(body)),
|
|
}
|
|
|
|
var envelope struct {
|
|
Error json.RawMessage `json:"error"`
|
|
}
|
|
if err := json.Unmarshal(body, &envelope); err != nil || len(envelope.Error) == 0 {
|
|
return apiError
|
|
}
|
|
if err := json.Unmarshal(envelope.Error, &apiError.Message); err == nil {
|
|
return apiError
|
|
}
|
|
_ = json.Unmarshal(envelope.Error, &apiError.Validation)
|
|
return apiError
|
|
}
|