Replies: 1 comment 3 replies
-
We can not change interfaces in Let me propose some other ways: I see you have I propose that you compose your own custom validator into "controller"like struct and use it like that: package users
import (
"context"
"github.com/labstack/echo/v4"
"net/http"
)
// this could have its own package if there are a lot of complex logic. ATM it is here to avoid cyclic imports
type validator interface {
ValidateCtx(ctx context.Context, i interface{}) error
}
type ctrl struct {
validator validator
}
func RegisterRoutes(root *echo.Group, validator validator) {
users := root.Group("/users")
c := ctrl{validator: validator}
users.POST("/", c.createUser)
}
func (ctrl *ctrl) createUser(c echo.Context) (err error) {
type User struct {
Name string `json:"name" validate:"required"`
Email string `json:"email" validate:"required,email"`
}
u := new(User)
if err = c.Bind(u); err != nil {
return echo.NewHTTPError(http.StatusBadRequest, err.Error())
}
if err = ctrl.validator.ValidateCtx(c.Request().Context(), u); err != nil {
return err
}
return c.JSON(http.StatusOK, u)
} and in your "top" level package. Could be func main() {
e := echo.New()
cValidator := &CV{validator: validator.New()}
e.Validator = cValidator
api := e.Group("/api")
users.RegisterRoutes(api, cValidator)
//groups.RegisterRoutes(api, cValidator)
e.Logger.Fatal(e.Start(":1323"))
}
// ------------------ this validator part could be its own package --------------------------------------
type CV struct {
validator *validator.Validate
}
func (cv *CV) Validate(i interface{}) error {
if err := cv.validator.Struct(i); err != nil {
// Optionally, you could return the error to give each route more control over the status code
return echo.NewHTTPError(http.StatusBadRequest, err.Error())
}
return nil
}
func (cv *CV) ValidateCtx(ctx context.Context, i interface{}) error {
if err := cv.validator.StructCtx(ctx, i); err != nil {
if _, ok := err.(*validator.InvalidValidationError); ok {
return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
} else {
return echo.NewHTTPError(http.StatusBadRequest, err.Error())
}
}
return nil
} |
Beta Was this translation helpful? Give feedback.
3 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Playground Validator, like some other validators allows
context.Context
to be passed into the validation method. For example, Playground Validator has bothStruct
andStructCtx
methods with the only difference being a firstctx
parameter.This is useful when there is a need to customize validation as per context. For example, the
ID
field might be required forPOST
but not forPATCH
(just an example). Allowing context to be passed in will open up some flexibility in the validation part. This can be achieved by extending theValidator interface
to allowValidateCtx(ctx context.Context, i interface{}) error
as well.Here is a sample:
Beta Was this translation helpful? Give feedback.
All reactions