mirror of
https://github.com/Noooste/garage-ui.git
synced 2026-08-08 04:43:12 +00:00
93 lines
2.3 KiB
Go
93 lines
2.3 KiB
Go
package apierr
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"io"
|
|
|
|
"github.com/Noooste/azuretls-client"
|
|
"github.com/minio/minio-go/v7"
|
|
)
|
|
|
|
// garageErrBody mirrors Garage's JSON error envelope.
|
|
type garageErrBody struct {
|
|
Code string `json:"code"`
|
|
Message string `json:"message"`
|
|
Region string `json:"region"`
|
|
Path string `json:"path"`
|
|
}
|
|
|
|
// ParseGarage returns nil for 2xx responses. For non-2xx it reads the body
|
|
// once, JSON-decodes the structured Garage error envelope, and returns a
|
|
// *UpstreamError. Malformed bodies are preserved verbatim in Message.
|
|
//
|
|
// ParseGarage DOES NOT close resp.RawBody on the success path — callers that
|
|
// decode the success body (decodeResponse in services/admin.go) still need
|
|
// access and are responsible for closing. On the error path the body is fully
|
|
// consumed before return.
|
|
func ParseGarage(resp *azuretls.Response) error {
|
|
if resp.StatusCode >= 200 && resp.StatusCode < 300 {
|
|
return nil
|
|
}
|
|
|
|
bodyBytes, _ := io.ReadAll(resp.RawBody)
|
|
|
|
ue := &UpstreamError{
|
|
HTTPStatus: resp.StatusCode,
|
|
Source: "garage",
|
|
}
|
|
|
|
var parsed garageErrBody
|
|
if len(bodyBytes) > 0 && json.Unmarshal(bodyBytes, &parsed) == nil && parsed.Code != "" {
|
|
ue.Code = parsed.Code
|
|
ue.Message = parsed.Message
|
|
ue.Details = map[string]string{}
|
|
if parsed.Region != "" {
|
|
ue.Details["region"] = parsed.Region
|
|
}
|
|
if parsed.Path != "" {
|
|
ue.Details["path"] = parsed.Path
|
|
}
|
|
} else {
|
|
ue.Message = string(bodyBytes)
|
|
}
|
|
return ue
|
|
}
|
|
|
|
// FromMinio converts a MinIO/S3 error into an *UpstreamError. Returns nil when
|
|
// err is nil. If err is not a minio.ErrorResponse (e.g. a network error), a
|
|
// generic 500 *UpstreamError is returned with the raw error string as Message.
|
|
func FromMinio(err error) *UpstreamError {
|
|
if err == nil {
|
|
return nil
|
|
}
|
|
|
|
var mer minio.ErrorResponse
|
|
if errors.As(err, &mer) {
|
|
details := map[string]string{}
|
|
if mer.BucketName != "" {
|
|
details["bucket"] = mer.BucketName
|
|
}
|
|
if mer.Key != "" {
|
|
details["key"] = mer.Key
|
|
}
|
|
status := mer.StatusCode
|
|
if status == 0 {
|
|
status = 500
|
|
}
|
|
return &UpstreamError{
|
|
HTTPStatus: status,
|
|
Code: mer.Code,
|
|
Message: mer.Message,
|
|
Source: "s3",
|
|
Details: details,
|
|
}
|
|
}
|
|
|
|
return &UpstreamError{
|
|
HTTPStatus: 500,
|
|
Source: "s3",
|
|
Message: err.Error(),
|
|
}
|
|
}
|