Change ErrorHandler signature
Similar to #1143, but for fiber Original issue: #1144
Due to differences in gin and fiber error handling, ErrorHandler option was modified in order to support fiber. Message type was changed to support errors.Is/As
// ErrorHandler is called when there is an error in validation
type ErrorHandler func(c *fiber.Ctx, message error, statusCode int) error
Usage example:
fibermiddleware.OapiRequestValidatorWithOptions(swagger, &fibermiddleware.Options{
ErrorHandler: func(c *fiber.Ctx, message error, statusCode int) error {
return c.Status(statusCode).JSON(fiber.Map{
"ok": false,
"error": message.Error(),
}) // .JSON error is returned instead of being logged manually. Fiber middlewares could handle them
},
})
Since we return error explicitly, all errors wrappings fmt.Errorf("something happened: %s", err) must be replaced with fmt.Errorf("something happened: %w", err) in order to use errors.Is/As
switch e := err.(type) {
case *openapi3filter.RequestError:
// We've got a bad request
// Split up the verbose error by lines and return the first one
// openapi errors seem to be multi-line with a decent message on the first
errorLines := strings.Split(e.Error(), "\n")
return fmt.Errorf("error in openapi3filter.RequestError: %s", errorLines[0])
case *openapi3filter.SecurityRequirementsError:
return fmt.Errorf("error in openapi3filter.SecurityRequirementsError: %w", e)
default:
// This should never happen today, but if our upstream code changes,
// we don't want to crash the server, so handle the unexpected error.
return fmt.Errorf("error validating request: %w", err)
}
}
So that we can determine in ErrorHandler whether error is BadRequest or Unauthorized
fibermiddleware.OapiRequestValidatorWithOptions(&specCopy, &fibermiddleware.Options{
ErrorHandler: func(c *fiber.Ctx, message error, statusCode int) error {
var securityRequirementsError *openapi3filter.SecurityRequirementsError
if errors.As(message, &securityRequirementsError) {
return api.SendUnauthorizedError(c, securityRequirementsError)
}
var requestError *openapi3filter.RequestError
if errors.As(message, &requestError) {
return api.SendBadRequestException(c, requestError)
}
return api.SendInternalError(c, message)
},
Thank you for this, and sorry it's taken so long for us to get to it - as part of https://github.com/oapi-codegen/nethttp-middleware/pull/35 we're looking at what a "better" OpenAPI validation middleware's error handling would look like and once that's merged, we'll look at pulling that into each of the separate middleware packages as needed