diff --git a/.golangci.yml b/.golangci.yml index b13799f5..c4cf919c 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -15,6 +15,7 @@ linters: - ineffassign - staticcheck - unused + - usestdlibvars linters-settings: gofumpt: diff --git a/examples/full-app-gourmet/server/server.go b/examples/full-app-gourmet/server/server.go index b3695ecc..f01f8918 100644 --- a/examples/full-app-gourmet/server/server.go +++ b/examples/full-app-gourmet/server/server.go @@ -23,7 +23,7 @@ func (rs Ressources) Setup( fuego.WithAutoAuth(controller.LoginFunc), fuego.WithTemplateFS(templates.FS), fuego.WithTemplateGlobs("**/*.html", "**/**/*.html"), - fuego.WithGlobalResponseTypes(403, "Forbidden"), + fuego.WithGlobalResponseTypes(http.StatusForbidden, "Forbidden"), } options = append(serverOptions, options...) diff --git a/examples/full-app-gourmet/views/views.go b/examples/full-app-gourmet/views/views.go index 3a3b14a1..39b60957 100644 --- a/examples/full-app-gourmet/views/views.go +++ b/examples/full-app-gourmet/views/views.go @@ -1,6 +1,7 @@ package views import ( + "net/http" "os" "github.com/go-fuego/fuego" @@ -24,7 +25,7 @@ func (rs Ressource) Routes(s *fuego.Server) { // Public Chunks fuego.Get(s, "/recipes-list", rs.showRecipesList) - fuego.Get(s, "/search", rs.searchRecipes).AddError(401, "Authorization Error").AddError(500, "My Server Error") + fuego.Get(s, "/search", rs.searchRecipes).AddError(http.StatusUnauthorized, "Authorization Error").AddError(500, "My Server Error") fuego.Get(s, "/ingredients/preselect-unit", rs.unitPreselected).QueryParam("id", "") // Admin Pages diff --git a/openapi_operations.go b/openapi_operations.go index ec86159a..510b5707 100644 --- a/openapi_operations.go +++ b/openapi_operations.go @@ -89,9 +89,12 @@ func (r Route[ResponseBody, RequestBody]) AddError(code int, description string, } func addResponse(s *Server, operation *openapi3.Operation, code int, description string, errorType ...any) { - responseSchema := schemaTagFromType(s, HTTPError{}) + var responseSchema schemaTag + if len(errorType) > 0 { responseSchema = schemaTagFromType(s, errorType[0]) + } else { + responseSchema = schemaTagFromType(s, HTTPError{}) } content := openapi3.NewContentWithSchemaRef(&responseSchema.SchemaRef, []string{"application/json"}) diff --git a/openapi_operations_test.go b/openapi_operations_test.go index de8a8ab1..2ee48699 100644 --- a/openapi_operations_test.go +++ b/openapi_operations_test.go @@ -72,6 +72,33 @@ func TestCustomError(t *testing.T) { require.Equal(t, "My Validation Error", *route.Operation.Responses.Map()["400"].Value.Description) } +func TestCustomErrorGlobalAndOnRoute(t *testing.T) { + type MyGlobalError struct { + Message string + } + s := NewServer( + WithGlobalResponseTypes(400, "My Global Error", MyGlobalError{}), + WithGlobalResponseTypes(501, "Another Global Error", MyGlobalError{}), + ) + + type MyLocalError struct { + Message string + } + + routeGlobal := Get(s, "/test-global", testController) + routeCustom := Get(s, "/test-custom", testController). + AddError(400, "My Local Error", MyLocalError{}). + AddError(419, "My Local Teapot") + + require.Equal(t, "My Global Error", *routeGlobal.Operation.Responses.Map()["400"].Value.Description, "Overrides Fuego's default 400 error") + require.Equal(t, "Another Global Error", *routeGlobal.Operation.Responses.Map()["501"].Value.Description) + + require.Equal(t, "My Local Error", *routeCustom.Operation.Responses.Map()["400"].Value.Description, "Local error overrides global error") + require.Equal(t, "My Local Teapot", *routeCustom.Operation.Responses.Map()["419"].Value.Description) + require.Equal(t, "Internal Server Error _(panics)_", *routeCustom.Operation.Responses.Map()["500"].Value.Description, "Global error set by default by Fuego") + require.Equal(t, "Another Global Error", *routeCustom.Operation.Responses.Map()["501"].Value.Description, "Global error is still available") +} + func TestCookieParams(t *testing.T) { t.Run("basic cookie", func(t *testing.T) { s := NewServer() diff --git a/options.go b/options.go index 7eab3b4a..f33192b0 100644 --- a/options.go +++ b/options.go @@ -115,8 +115,8 @@ func NewServer(options ...func(*Server)) *Server { WithSerializer(Send), WithErrorSerializer(SendError), WithErrorHandler(ErrorHandler), - WithGlobalResponseTypes(400, "Bad Request _(validation or deserialization error)_", HTTPError{}), - WithGlobalResponseTypes(500, "Internal Server Error _(panics)_", HTTPError{}), + WithGlobalResponseTypes(http.StatusBadRequest, "Bad Request _(validation or deserialization error)_", HTTPError{}), + WithGlobalResponseTypes(http.StatusInternalServerError, "Internal Server Error _(panics)_", HTTPError{}), } for _, option := range append(defaultOptions[:], options...) {