-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Context#BindAndValidate() #1105
Comments
I recommend you just implement your custom binder that would perform validation. |
Any updates? |
I implemented this in my own project as follows: // BindValidate simply combines echo.Context.Bind and echo.Context.Validate for the forms.
func BindValidate(c echo.Context, form interface{}) (err error) {
if err = c.Bind(form); err != nil {
return
}
return c.Validate(form)
} Although I think it would make more sense to directly do the validation during the "Bind" function conditionally if the context.Validator is set. |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
@vishr @aldas What do you think about revisiting this issue? With the current implementation, post-bind validation is not possible. Or does not produce the expected result. Given an model such as: type RequestModel struct {
Include bool `query:"include" validation:"required"`
} and a request such as: Validation will fail, because There is no way to know if it's false because it's the default value or whether it came in the request. Expected result
|
@lordzsolt your your case probably changing Validation works on already bound data and if field does not support "not existing state" then "required" can not fail. See this example: func main() {
e := echo.New()
e.Use(middleware.Logger())
e.Use(middleware.Recover())
e.GET("/", func(c echo.Context) error {
type RequestModel struct {
Include *bool `query:"include" validation:"required"`
}
rm := RequestModel{}
if err := c.Bind(&rm); err != nil {
return err
}
include := "empty"
if rm.Include != nil {
include = fmt.Sprintf("%v", *rm.Include)
}
return c.String(http.StatusOK, fmt.Sprintf("rm=%+v, include=%v\n", rm, include))
})
log.Fatal(e.Start(":8080"))
} Output: x@x:~/code$ curl "http://localhost:8080/?include=true"
rm={Include:0xc000024fd8}, include=true
x@x:~/code$ curl "http://localhost:8080/?"
rm={Include:<nil>}, include=empty For reference: this is how https://github.com/go-playground/validator handles |
side note: if default values that differ from "value type default value" are needed then try newer binder that Echo has err := echo.QueryParamsBinder(c).
Bool("include", &rm.Include).
BindError() Full example: func main() {
e := echo.New()
e.Use(middleware.Logger())
e.Use(middleware.Recover())
e.GET("/", func(c echo.Context) error {
type RequestModel struct {
Include bool // note: `echo.QueryParamsBinder` does not use struct tags
}
rm := RequestModel{
Include: true, // set you default value that is not overwritten when query param does not exist
}
err := echo.QueryParamsBinder(c).
Bool("include", &rm.Include).
BindError()
if err != nil {
return err
}
return c.String(http.StatusOK, fmt.Sprintf("rm=%+v\n", rm))
})
log.Fatal(e.Start(":8080"))
} Output: x@x:~/code$ curl "http://localhost:8080/?include=true"
rm={Include:true}
x@x:~/code$ curl "http://localhost:8080/?include=false"
rm={Include:false}
x@x:~/code$ curl "http://localhost:8080/?"
rm={Include:true} |
With the current implementation, yes. That's the reason I pinged you to ask about your opinion. What I would imagine happening is that validation would happen within Here, you can validate that all the fields marked In essence, the contents of |
This would be applicable only for query params/form fields/headers/cookies and not for json etc. JSON/XML have their own bind implementations that Echo only wraps. So if you are binding to json to struct there is no way to my knowledge to know if field existed or not. I do not think that validating My suggestion is that: in your handler have temporary struct, in to where you are binding your request data. Do validation on that struct which scope is only that handler method. If validation passes then map bound data to DTO or domain object and pass to business logic/service. So then you are not directly passing that struct you can be generous with fields being pointers and you do not have to deal nil check in business logic. If you want to do validation in business code and still check for It is safer not to pass bound struct directly to business logic - see first example here #1670 (comment) |
Note for future: you can create custom binder that wraps default binder and contains validation part. In this thread there are couple of ways to do it #438 |
@aldas I mean yes, obviously this is possible. But the whole point of using I feel like it would be a reasonable expectation for The |
Although I'd love to have this feature baked into the library, I've resorted to this CustomBinder:
Hope it helps someone. |
No description provided.
The text was updated successfully, but these errors were encountered: