Skip to content

Commit 9879d43

Browse files
authored
Add ErrorHandler for middleware (#557)
1 parent d72a8e3 commit 9879d43

File tree

2 files changed

+20
-4
lines changed

2 files changed

+20
-4
lines changed

oapi_validate.go

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,10 @@ import (
2929
"github.com/gin-gonic/gin"
3030
)
3131

32-
const GinContextKey = "oapi-codegen/gin-context"
33-
const UserDataKey = "oapi-codegen/user-data"
32+
const (
33+
GinContextKey = "oapi-codegen/gin-context"
34+
UserDataKey = "oapi-codegen/user-data"
35+
)
3436

3537
// Create validator middleware from a YAML file path
3638
func OapiValidatorFromYamlFile(path string) (gin.HandlerFunc, error) {
@@ -54,9 +56,13 @@ func OapiRequestValidator(swagger *openapi3.T) gin.HandlerFunc {
5456
return OapiRequestValidatorWithOptions(swagger, nil)
5557
}
5658

59+
// ErrorHandler is called when there is an error in validation
60+
type ErrorHandler func(c *gin.Context, message string, statusCode int)
61+
5762
// Options to customize request validation. These are passed through to
5863
// openapi3filter.
5964
type Options struct {
65+
ErrorHandler ErrorHandler
6066
Options openapi3filter.Options
6167
ParamDecoder openapi3filter.ContentParameterDecoder
6268
UserData interface{}
@@ -71,8 +77,14 @@ func OapiRequestValidatorWithOptions(swagger *openapi3.T, options *Options) gin.
7177
return func(c *gin.Context) {
7278
err := ValidateRequestFromContext(c, router, options)
7379
if err != nil {
74-
// note: i am not sure if this is the best way to handle this
75-
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()})
80+
if options != nil && options.ErrorHandler != nil {
81+
options.ErrorHandler(c, err.Error(), http.StatusBadRequest)
82+
// in case the handler didn't internally call Abort, stop the chain
83+
c.Abort()
84+
} else {
85+
// note: i am not sure if this is the best way to handle this
86+
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()})
87+
}
7688
}
7789
c.Next()
7890
}

oapi_validate_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,9 @@ func TestOapiRequestValidator(t *testing.T) {
136136
// Set up an authenticator to check authenticated function. It will allow
137137
// access to "someScope", but disallow others.
138138
options := Options{
139+
ErrorHandler: func(c *gin.Context, message string, statusCode int) {
140+
c.String(statusCode, "test: "+message)
141+
},
139142
Options: openapi3filter.Options{
140143
AuthenticationFunc: func(c context.Context, input *openapi3filter.AuthenticationInput) error {
141144
// The gin context should be propagated into here.
@@ -265,6 +268,7 @@ func TestOapiRequestValidator(t *testing.T) {
265268
{
266269
rec := doGet(t, g, "http://deepmap.ai/protected_resource_401")
267270
assert.Equal(t, http.StatusBadRequest, rec.Code)
271+
assert.Equal(t, "test: error in openapi3filter.SecurityRequirementsError: Security requirements failed", rec.Body.String())
268272
assert.False(t, called, "Handler should not have been called")
269273
called = false
270274
}

0 commit comments

Comments
 (0)