Skip to content

Commit be28747

Browse files
committed
refactor: migrate error to a method parameter, not part of ErrorHandlerOpts
While writing the documentation for this, it didn't feel quite right to note that the `error` wasn't part of the method signature, despite it being very important for the actual handling of errors.
1 parent 124a344 commit be28747

File tree

2 files changed

+20
-26
lines changed

2 files changed

+20
-26
lines changed

oapi_validate.go

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -30,25 +30,22 @@ type ErrorHandler func(w http.ResponseWriter, message string, statusCode int)
3030

3131
// ErrorHandlerWithOpts is called when there is an error in validation, with more information about the `error` that occurred and which request is currently being processed.
3232
//
33+
// There are a number of known types that the `error` can be:
34+
//
35+
// - `*openapi3filter.SecurityRequirementsError` - if the `AuthenticationFunc` has failed to authenticate the request
36+
// - `*openapi3filter.RequestError` - if a bad request has been made
37+
//
38+
// Additionally, if you have set `openapi3filter.Options#MultiError`:
39+
//
40+
// - `openapi3.MultiError` (https://pkg.go.dev/github.com/getkin/kin-openapi/openapi3#MultiError)
41+
//
3342
// If both an `ErrorHandlerWithOpts` and `ErrorHandler` are set, the `ErrorHandlerWithOpts` takes precedence.
3443
//
3544
// NOTE that this should ideally be used instead of ErrorHandler
36-
type ErrorHandlerWithOpts func(ctx context.Context, w http.ResponseWriter, r *http.Request, opts ErrorHandlerOpts)
45+
type ErrorHandlerWithOpts func(ctx context.Context, err error, w http.ResponseWriter, r *http.Request, opts ErrorHandlerOpts)
3746

3847
// ErrorHandlerOpts contains additional options that are passed to the `ErrorHandlerWithOpts` function in the case of an error being returned by the middleware
3948
type ErrorHandlerOpts struct {
40-
// Error is the underlying error that triggered this error handler to be executed.
41-
//
42-
// Known error types:
43-
//
44-
// - `*openapi3filter.SecurityRequirementsError` - if the `AuthenticationFunc` has failed to authenticate the request
45-
// - `*openapi3filter.RequestError` - if a bad request has been made
46-
//
47-
// Additionally, if you have set `openapi3filter.Options#MultiError`:
48-
//
49-
// - `openapi3.MultiError` (https://pkg.go.dev/github.com/getkin/kin-openapi/openapi3#MultiError)
50-
Error error
51-
5249
// StatusCode indicates the HTTP Status Code that the OpenAPI validation middleware _suggests_ is returned to the user.
5350
//
5451
// NOTE that this is very much a suggestion, and can be overridden if you believe you have a better approach.
@@ -163,11 +160,10 @@ func performRequestValidationForErrorHandlerWithOpts(next http.Handler, w http.R
163160
if err != nil {
164161
errOpts := ErrorHandlerOpts{
165162
// MatchedRoute will be nil, as we've not matched a route we know about
166-
Error: err,
167163
StatusCode: http.StatusNotFound,
168164
}
169165

170-
options.ErrorHandlerWithOpts(r.Context(), w, r, errOpts)
166+
options.ErrorHandlerWithOpts(r.Context(), err, w, r, errOpts)
171167
return
172168
}
173169

@@ -197,26 +193,28 @@ func performRequestValidationForErrorHandlerWithOpts(next http.Handler, w http.R
197193
return
198194
}
199195

196+
var theErr error
197+
200198
switch e := err.(type) {
201199
case openapi3.MultiError:
202-
errOpts.Error = e
200+
theErr = e
203201
errOpts.StatusCode = determineStatusCodeForMultiError(e)
204202
case *openapi3filter.RequestError:
205203
// We've got a bad request
206-
errOpts.Error = e
204+
theErr = e
207205
errOpts.StatusCode = http.StatusBadRequest
208206
case *openapi3filter.SecurityRequirementsError:
209-
errOpts.Error = e
207+
theErr = e
210208
errOpts.StatusCode = http.StatusUnauthorized
211209
default:
212210
// This should never happen today, but if our upstream code changes,
213211
// we don't want to crash the server, so handle the unexpected error.
214212
// return http.StatusInternalServerError,
215-
errOpts.Error = fmt.Errorf("error validating route: %w", e)
213+
theErr = fmt.Errorf("error validating route: %w", e)
216214
errOpts.StatusCode = http.StatusUnauthorized
217215
}
218216

219-
options.ErrorHandlerWithOpts(r.Context(), w, r, errOpts)
217+
options.ErrorHandlerWithOpts(r.Context(), theErr, w, r, errOpts)
220218
}
221219

222220
// validateRequest is called from the middleware above and actually does the work

oapi_validate_example_test.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -469,9 +469,7 @@ components:
469469
return fmt.Errorf("this check always fails - don't let anyone in!")
470470
}
471471

472-
errorHandlerFunc := func(ctx context.Context, w http.ResponseWriter, r *http.Request, opts middleware.ErrorHandlerOpts) {
473-
err := opts.Error
474-
472+
errorHandlerFunc := func(ctx context.Context, err error, w http.ResponseWriter, r *http.Request, opts middleware.ErrorHandlerOpts) {
475473
if opts.MatchedRoute == nil {
476474
fmt.Printf("ErrorHandlerWithOpts: An HTTP %d was returned by the middleware with error message: %s\n", opts.StatusCode, err.Error())
477475

@@ -716,9 +714,7 @@ paths:
716714
w.WriteHeader(http.StatusMethodNotAllowed)
717715
})
718716

719-
errorHandlerFunc := func(ctx context.Context, w http.ResponseWriter, r *http.Request, opts middleware.ErrorHandlerOpts) {
720-
err := opts.Error
721-
717+
errorHandlerFunc := func(ctx context.Context, err error, w http.ResponseWriter, r *http.Request, opts middleware.ErrorHandlerOpts) {
722718
if opts.MatchedRoute == nil {
723719
fmt.Printf("ErrorHandlerWithOpts: An HTTP %d was returned by the middleware with error message: %s\n", opts.StatusCode, err.Error())
724720

0 commit comments

Comments
 (0)