mirror of
https://github.com/crowdsecurity/crowdsec.git
synced 2025-05-11 04:15:54 +02:00
* metrics: avoid nil deref with inactive bouncers * log message from API even it if cannot be parsed * fix unit test
61 lines
1.4 KiB
Go
61 lines
1.4 KiB
Go
package apiclient
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
|
|
"github.com/crowdsecurity/go-cs-lib/ptr"
|
|
|
|
"github.com/crowdsecurity/crowdsec/pkg/models"
|
|
)
|
|
|
|
type ErrorResponse struct {
|
|
models.ErrorResponse
|
|
}
|
|
|
|
func (e *ErrorResponse) Error() string {
|
|
message := ptr.OrEmpty(e.Message)
|
|
errors := ""
|
|
|
|
if len(e.Errors) > 0 {
|
|
errors = fmt.Sprintf(" (%s)", e.Errors)
|
|
}
|
|
|
|
if message == "" && errors == "" {
|
|
errors = "(no errors)"
|
|
}
|
|
|
|
return fmt.Sprintf("API error: %s%s", message, errors)
|
|
}
|
|
|
|
// CheckResponse verifies the API response and builds an appropriate Go error if necessary.
|
|
func CheckResponse(r *http.Response) error {
|
|
if c := r.StatusCode; 200 <= c && c <= 299 || c == 304 {
|
|
return nil
|
|
}
|
|
|
|
ret := &ErrorResponse{}
|
|
|
|
data, err := io.ReadAll(r.Body)
|
|
if err != nil || len(data) == 0 {
|
|
ret.Message = ptr.Of(fmt.Sprintf("http code %d, no response body", r.StatusCode))
|
|
return ret
|
|
}
|
|
|
|
switch r.StatusCode {
|
|
case http.StatusUnprocessableEntity:
|
|
ret.Message = ptr.Of(fmt.Sprintf("http code %d, invalid request: %s", r.StatusCode, string(data)))
|
|
default:
|
|
// try to unmarshal and if there are no 'message' or 'errors' fields, display the body as is,
|
|
// the API is following a different convention
|
|
err := json.Unmarshal(data, ret)
|
|
if err != nil || (ret.Message == nil && len(ret.Errors) == 0) {
|
|
ret.Message = ptr.Of(fmt.Sprintf("http code %d, response: %s", r.StatusCode, string(data)))
|
|
return ret
|
|
}
|
|
}
|
|
|
|
return ret
|
|
}
|