You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Historically, handling errors with the OpenAPI request validation
middleware has been fairly frustrating, as we don't provide information
around the `error` that occurred (only the message), the
`context.Context` that this request is for, what HTTP method + path it's
for, or anything else about the request.
As a means to much more greatly improve the experience for our users, we
can introduce a new `ErrorHandlerWithOpts` function which provides all this
information, and the ability to extend this in the future.
This is introduced in a backwards-compatible way, with a new function,
to avoid a breaking change, and to allow consumers to migrate over to
the new function.
We'll mark the existing function as deprecated, to indicate folks should
migrate over, but also note there is no hard requirement or deadline
associated.
This introduces a new helper method
`performRequestValidationForErrorHandler` that will be used alongside
the new `performRequestValidationForErrorHandlerWithOpts` for the new
function, as a means to deduplicate processing the error itself.
We want to make sure that our testable examples add validation for this
functionality, as well as indicating how a `MultiError` could be handled
(with added complexity).
With thanks to Per, Mike and MattiasMartens who have made tangible
efforts towards this in this repository, as well as many others in the
past who have worked on suggestions and improvements towards this.
Closes#11, #27.
Co-authored-by: Per Bockman <[email protected]>
Co-authored-by: Mike Schinkel <[email protected]>
Co-authored-by: MattiasMartens <[email protected]>
Copy file name to clipboardExpand all lines: oapi_validate.go
+176-14
Original file line number
Diff line number
Diff line change
@@ -8,6 +8,7 @@
8
8
package nethttpmiddleware
9
9
10
10
import (
11
+
"context"
11
12
"errors"
12
13
"fmt"
13
14
"log"
@@ -21,8 +22,58 @@ import (
21
22
)
22
23
23
24
// ErrorHandler is called when there is an error in validation
25
+
//
26
+
// If both an `ErrorHandlerWithOpts` and `ErrorHandler` are set, the `ErrorHandlerWithOpts` takes precedence.
27
+
//
28
+
// Deprecated: it's recommended you migrate to the ErrorHandlerWithOpts, as it provides more control over how to handle an error that occurs, including giving direct access to the `error` itself. There are no plans to remove this method.
// 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.
32
+
//
33
+
// If both an `ErrorHandlerWithOpts` and `ErrorHandler` are set, the `ErrorHandlerWithOpts` takes precedence.
34
+
//
35
+
// NOTE that this should ideally be used instead of ErrorHandler
36
+
typeErrorHandlerWithOptsfunc(ctx context.Context, w http.ResponseWriter, r*http.Request, optsErrorHandlerOpts)
37
+
38
+
// ErrorHandlerOpts contains additional options that are passed to the `ErrorHandlerWithOpts` function in the case of an error being returned by the middleware
39
+
typeErrorHandlerOptsstruct {
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`:
// StatusCode indicates the HTTP Status Code that the OpenAPI validation middleware _suggests_ is returned to the user.
53
+
//
54
+
// NOTE that this is very much a suggestion, and can be overridden if you believe you have a better approach.
55
+
StatusCodeint
56
+
57
+
// MatchedRoute is the underlying path that this request is being matched against.
58
+
//
59
+
// This is the route according to the OpenAPI validation middleware, and can be used in addition to/instead of the `http.Request`
60
+
//
61
+
// NOTE that this will be nil if there is no matched route (i.e. a request has been sent to an endpoint not in the OpenAPI spec)
62
+
MatchedRoute*ErrorHandlerOptsMatchedRoute
63
+
}
64
+
65
+
typeErrorHandlerOptsMatchedRoutestruct {
66
+
// Route indicates the Route that this error is received by.
67
+
//
68
+
// This can be used in addition to/instead of the `http.Request`.
69
+
Route*routers.Route
70
+
71
+
// PathParams are any path parameters that are determined from the request.
72
+
//
73
+
// This can be used in addition to/instead of the `http.Request`.
74
+
PathParamsmap[string]string
75
+
}
76
+
26
77
// MultiErrorHandler is called when the OpenAPI filter returns an openapi3.MultiError (https://pkg.go.dev/github.com/getkin/kin-openapi/openapi3#MultiError)
// ErrorHandler is called when a validation error occurs.
34
85
//
86
+
// If both an `ErrorHandlerWithOpts` and `ErrorHandler` are set, the `ErrorHandlerWithOpts` takes precedence.
87
+
//
35
88
// If not provided, `http.Error` will be called
36
89
ErrorHandlerErrorHandler
90
+
91
+
// ErrorHandlerWithOpts is called when there is an error in validation.
92
+
//
93
+
// If both an `ErrorHandlerWithOpts` and `ErrorHandler` are set, the `ErrorHandlerWithOpts` takes precedence.
94
+
ErrorHandlerWithOptsErrorHandlerWithOpts
95
+
37
96
// MultiErrorHandler is called when there is an openapi3.MultiError (https://pkg.go.dev/github.com/getkin/kin-openapi/openapi3#MultiError) returned by the `openapi3filter`.
38
97
//
39
98
// If not provided `defaultMultiErrorHandler` will be used.
99
+
//
100
+
// Does not get called when using `ErrorHandlerWithOpts`
40
101
MultiErrorHandlerMultiErrorHandler
41
102
// SilenceServersWarning allows silencing a warning for https://github.com/deepmap/oapi-codegen/issues/882 that reports when an OpenAPI spec has `spec.Servers != nil`
// Note that this is an inline-and-modified version of `validateRequest`, with a simplified control flow and providing full access to the `error` for the `ErrorHandlerWithOpts` function.
154
+
funcperformRequestValidationForErrorHandlerWithOpts(next http.Handler, w http.ResponseWriter, r*http.Request, router routers.Router, options*Options) {
155
+
// Find route
156
+
route, pathParams, err:=router.FindRoute(r)
157
+
iferr!=nil {
158
+
errOpts:=ErrorHandlerOpts{
159
+
// MatchedRoute will be nil, as we've not matched a route we know about
0 commit comments