fix: add information about target response into error message if inte… (#8281)

# Which Problems Are Solved

Execution responses with HTTP StatusCode not equal to 200 interrupt the
client request silently.

# How the Problems Are Solved

Adds information about the recieved StatusCode and Body into the error
if StatusCode not 200.

# Additional Context

Closes #8177

---------

Co-authored-by: Elio Bischof <elio@zitadel.com>
Co-authored-by: Livio Spring <livio.a@gmail.com>
This commit is contained in:
Stefan Benz
2024-08-16 11:26:15 +02:00
committed by GitHub
parent 11d01b9b35
commit 83c78a470c
21 changed files with 400 additions and 6 deletions

View File

@@ -45,3 +45,36 @@ func ZitadelErrorToHTTPStatusCode(err error) (statusCode int, ok bool) {
return http.StatusInternalServerError, false
}
}
func HTTPStatusCodeToZitadelError(parent error, statusCode int, id string, message string) error {
if statusCode == http.StatusOK {
return nil
}
var errorFunc func(parent error, id, message string) error
switch statusCode {
case http.StatusConflict:
errorFunc = zerrors.ThrowAlreadyExists
case http.StatusGatewayTimeout:
errorFunc = zerrors.ThrowDeadlineExceeded
case http.StatusInternalServerError:
errorFunc = zerrors.ThrowInternal
case http.StatusBadRequest:
errorFunc = zerrors.ThrowInvalidArgument
case http.StatusNotFound:
errorFunc = zerrors.ThrowNotFound
case http.StatusForbidden:
errorFunc = zerrors.ThrowPermissionDenied
case http.StatusUnauthorized:
errorFunc = zerrors.ThrowUnauthenticated
case http.StatusServiceUnavailable:
errorFunc = zerrors.ThrowUnavailable
case http.StatusNotImplemented:
errorFunc = zerrors.ThrowUnimplemented
case http.StatusTooManyRequests:
errorFunc = zerrors.ThrowResourceExhausted
default:
errorFunc = zerrors.ThrowUnknown
}
return errorFunc(parent, id, message)
}

View File

@@ -6,6 +6,8 @@ import (
"net/http"
"testing"
"github.com/stretchr/testify/assert"
"github.com/zitadel/zitadel/internal/zerrors"
)
@@ -136,3 +138,152 @@ func TestZitadelErrorToHTTPStatusCode(t *testing.T) {
})
}
}
func TestHTTPStatusCodeToZitadelError(t *testing.T) {
type args struct {
statusCode int
id string
message string
parent error
}
tests := []struct {
name string
args args
wantErr error
}{
{
name: "StatusOK",
args: args{
statusCode: http.StatusOK,
},
wantErr: nil,
},
{
name: "StatusConflict",
args: args{
statusCode: http.StatusConflict,
id: "id",
message: "message",
},
wantErr: zerrors.ThrowAlreadyExists(nil, "id", "message"),
},
{
name: "StatusGatewayTimeout",
args: args{
statusCode: http.StatusGatewayTimeout,
id: "id",
message: "message",
},
wantErr: zerrors.ThrowDeadlineExceeded(nil, "id", "message"),
},
{
name: "StatusInternalServerError",
args: args{
statusCode: http.StatusInternalServerError,
id: "id",
message: "message",
},
wantErr: zerrors.ThrowInternal(nil, "id", "message"),
},
{
name: "StatusBadRequest",
args: args{
statusCode: http.StatusBadRequest,
id: "id",
message: "message",
},
wantErr: zerrors.ThrowInvalidArgument(nil, "id", "message"),
},
{
name: "StatusNotFound",
args: args{
statusCode: http.StatusNotFound,
id: "id",
message: "message",
},
wantErr: zerrors.ThrowNotFound(nil, "id", "message"),
},
{
name: "StatusForbidden",
args: args{
statusCode: http.StatusForbidden,
id: "id",
message: "message",
},
wantErr: zerrors.ThrowPermissionDenied(nil, "id", "message"),
},
{
name: "StatusUnauthorized",
args: args{
statusCode: http.StatusUnauthorized,
id: "id",
message: "message",
},
wantErr: zerrors.ThrowUnauthenticated(nil, "id", "message"),
},
{
name: "StatusServiceUnavailable",
args: args{
statusCode: http.StatusServiceUnavailable,
id: "id",
message: "message",
},
wantErr: zerrors.ThrowUnavailable(nil, "id", "message"),
},
{
name: "StatusNotImplemented",
args: args{
statusCode: http.StatusNotImplemented,
id: "id",
message: "message",
},
wantErr: zerrors.ThrowUnimplemented(nil, "id", "message"),
},
{
name: "StatusTooManyRequests",
args: args{
statusCode: http.StatusTooManyRequests,
id: "id",
message: "message",
},
wantErr: zerrors.ThrowResourceExhausted(nil, "id", "message"),
},
{
name: "Unknown",
args: args{
statusCode: 1000,
id: "id",
message: "message",
},
wantErr: zerrors.ThrowUnknown(nil, "id", "message"),
},
{
name: "Unknown, test for statuscode",
args: args{
statusCode: 1000,
id: "id",
message: "message",
},
wantErr: zerrors.ThrowError(nil, "id", "message"),
},
{
name: "Unknown with parent",
args: args{
statusCode: 1000,
id: "id",
message: "message",
parent: errors.New("parent error"),
},
wantErr: zerrors.ThrowUnknown(nil, "id", "message"),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := HTTPStatusCodeToZitadelError(tt.args.parent, tt.args.statusCode, tt.args.id, tt.args.message)
assert.ErrorIs(t, err, tt.wantErr)
if tt.args.parent != nil {
assert.ErrorIs(t, err, tt.args.parent)
}
})
}
}