feat(gitea): typed error mapping from http status
This commit is contained in:
34
internal/gitea/errors.go
Normal file
34
internal/gitea/errors.go
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrPermissionDenied = errors.New("permission denied")
|
||||||
|
ErrNotFound = errors.New("not found")
|
||||||
|
ErrConflict = errors.New("conflict")
|
||||||
|
ErrValidation = errors.New("validation failed")
|
||||||
|
ErrUpstream = errors.New("upstream gitea error")
|
||||||
|
)
|
||||||
|
|
||||||
|
// MapStatus returns nil for 2xx, otherwise a typed error wrapping the response body.
|
||||||
|
func MapStatus(status int, body []byte) error {
|
||||||
|
if status >= 200 && status < 300 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case status == 401, status == 403:
|
||||||
|
return fmt.Errorf("%w: %s", ErrPermissionDenied, body)
|
||||||
|
case status == 404:
|
||||||
|
return fmt.Errorf("%w: %s", ErrNotFound, body)
|
||||||
|
case status == 409:
|
||||||
|
return fmt.Errorf("%w: %s", ErrConflict, body)
|
||||||
|
case status == 422:
|
||||||
|
return fmt.Errorf("%w: %s", ErrValidation, body)
|
||||||
|
case status >= 500:
|
||||||
|
return fmt.Errorf("%w (status %d)", ErrUpstream, status)
|
||||||
|
}
|
||||||
|
return fmt.Errorf("unexpected status %d: %s", status, body)
|
||||||
|
}
|
||||||
34
internal/gitea/errors_test.go
Normal file
34
internal/gitea/errors_test.go
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
package gitea_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"gitea.d-ma.be/mathias/gitea-mcp/internal/gitea"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMapStatus(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
status int
|
||||||
|
want error
|
||||||
|
}{
|
||||||
|
{401, gitea.ErrPermissionDenied},
|
||||||
|
{403, gitea.ErrPermissionDenied},
|
||||||
|
{404, gitea.ErrNotFound},
|
||||||
|
{409, gitea.ErrConflict},
|
||||||
|
{422, gitea.ErrValidation},
|
||||||
|
{500, gitea.ErrUpstream},
|
||||||
|
{502, gitea.ErrUpstream},
|
||||||
|
{200, nil},
|
||||||
|
{299, nil},
|
||||||
|
}
|
||||||
|
for _, tc := range cases {
|
||||||
|
got := gitea.MapStatus(tc.status, []byte(`{"message":"x"}`))
|
||||||
|
if tc.want == nil {
|
||||||
|
assert.NoError(t, got)
|
||||||
|
} else {
|
||||||
|
assert.True(t, errors.Is(got, tc.want), "status %d", tc.status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user