-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f05de16
commit f23832e
Showing
12 changed files
with
194 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package v1 | ||
|
||
import "net/http" | ||
|
||
var ErrorCodeMapping = map[ErrorCode]int{ | ||
ParameterInvalid: http.StatusBadRequest, | ||
ParameterMissing: http.StatusBadRequest, | ||
ProcessingError: http.StatusInternalServerError, | ||
ResourceAlreadyExists: http.StatusConflict, | ||
ResourceMissing: http.StatusNotFound, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package handler | ||
|
||
import ( | ||
"encoding/json" | ||
"net/http" | ||
|
||
"github.com/glass-cms/glasscms/lib/mediatype" | ||
) | ||
|
||
// RespondWithJSON writes a JSON response to the response. | ||
func RespondWithJSON[T any](w http.ResponseWriter, statusCode int, data T) { | ||
w.Header().Set("Content-Type", mediatype.ApplicationJSON) | ||
w.WriteHeader(statusCode) | ||
|
||
if err := json.NewEncoder(w).Encode(data); err != nil { | ||
http.Error(w, "Failed to encode JSON", http.StatusInternalServerError) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package v1 | ||
|
||
import ( | ||
"net/http" | ||
"reflect" | ||
|
||
v1 "github.com/glass-cms/glasscms/api/v1" | ||
"github.com/glass-cms/glasscms/server/handler" | ||
) | ||
|
||
// ErrorMapper is a function that maps an error to an API error response. | ||
type ErrorMapper func(error) *v1.Error | ||
|
||
type ErrorHandler struct { | ||
Mappers map[reflect.Type]ErrorMapper | ||
} | ||
|
||
// NewErrorHandler returns a new instance of ErrorHandler. | ||
func NewErrorHandler() *ErrorHandler { | ||
return &ErrorHandler{ | ||
Mappers: make(map[reflect.Type]ErrorMapper), | ||
} | ||
} | ||
|
||
// RegisterErrorMapper registers an error mapper for a specific error type. | ||
func (h *ErrorHandler) RegisterErrorMapper(errType reflect.Type, mapper ErrorMapper) { | ||
h.Mappers[errType] = mapper | ||
} | ||
|
||
// HandleError handles an error by writing an appropriate response to the client. | ||
func (h *ErrorHandler) HandleError(w http.ResponseWriter, _ *http.Request, err error) { | ||
if err == nil { | ||
return | ||
} | ||
|
||
errType := reflect.TypeOf(err) | ||
if mapper, exists := h.Mappers[errType]; exists { | ||
errResp := mapper(err) | ||
|
||
statusCode, ok := v1.ErrorCodeMapping[errResp.Code] | ||
if !ok { | ||
statusCode = http.StatusInternalServerError | ||
} | ||
|
||
handler.RespondWithJSON(w, statusCode, errResp) | ||
} | ||
|
||
// TODO: Default error handling. | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
package v1_test |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package v1 | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
|
||
v1 "github.com/glass-cms/glasscms/api/v1" | ||
"github.com/glass-cms/glasscms/lib/resource" | ||
) | ||
|
||
// ErrorMapperAlreadyExistsError maps a resource.AlreadyExistsError to an API error response. | ||
func ErrorMapperAlreadyExistsError(err error) *v1.Error { | ||
var alreadyExistsErr *resource.AlreadyExistsError | ||
if !errors.As(err, &alreadyExistsErr) { | ||
panic("error is not a resource.AlreadyExistsError") | ||
} | ||
|
||
return &v1.Error{ | ||
Code: v1.ResourceAlreadyExists, | ||
Message: fmt.Sprintf("An %s with the name already exists", alreadyExistsErr.Resource), | ||
Type: v1.ApiError, | ||
Details: map[string]interface{}{ | ||
"resource": alreadyExistsErr.Resource, | ||
"name": alreadyExistsErr.Name, | ||
}, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package v1_test | ||
|
||
import ( | ||
"errors" | ||
"testing" | ||
|
||
v1 "github.com/glass-cms/glasscms/api/v1" | ||
"github.com/glass-cms/glasscms/lib/resource" | ||
v1_handler "github.com/glass-cms/glasscms/server/handler/v1" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestErrorMapperAlreadyExistsError(t *testing.T) { | ||
t.Parallel() | ||
|
||
type args struct { | ||
err error | ||
} | ||
tests := map[string]struct { | ||
args args | ||
want *v1.Error | ||
expectPanics bool | ||
}{ | ||
"maps resource.AlreadyExistsError to an API error response": { | ||
args: args{ | ||
err: resource.NewAlreadyExistsError("item1", "item", errors.New("underlying error")), | ||
}, | ||
want: &v1.Error{ | ||
Code: v1.ResourceAlreadyExists, | ||
Message: "An item with the name already exists", | ||
Type: v1.ApiError, | ||
Details: map[string]interface{}{ | ||
"resource": "item", | ||
"name": "item1", | ||
}, | ||
}, | ||
}, | ||
"panics if error is not a resource.AlreadyExistsError": { | ||
args: args{ | ||
err: errors.New("some error"), | ||
}, | ||
expectPanics: true, | ||
}, | ||
} | ||
for name, tt := range tests { | ||
t.Run(name, func(t *testing.T) { | ||
t.Parallel() | ||
|
||
if tt.expectPanics { | ||
require.Panics(t, func() { | ||
v1_handler.ErrorMapperAlreadyExistsError(tt.args.err) | ||
}) | ||
return | ||
} | ||
|
||
require.Equal(t, tt.want, v1_handler.ErrorMapperAlreadyExistsError(tt.args.err)) | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters