Request Validation
Learn how to validate requests in Iris.
Basic Validation
go
package main
import (
"github.com/kataras/iris/v12"
"github.com/go-playground/validator/v10"
)
type User struct {
Name string `json:"name" validate:"required,min=2"`
Email string `json:"email" validate:"required,email"`
Age int `json:"age" validate:"required,gte=0,lte=130"`
Password string `json:"password" validate:"required,min=8"`
}
func main() {
app := iris.New()
validate := validator.New()
app.Post("/users", func(ctx iris.Context) {
var user User
if err := ctx.ReadJSON(&user); err != nil {
ctx.StopWithError(iris.StatusBadRequest, err)
return
}
if err := validate.Struct(user); err != nil {
if validationErrors, ok := err.(validator.ValidationErrors); ok {
errors := make([]string, len(validationErrors))
for i, e := range validationErrors {
errors[i] = e.Field() + " failed " + e.Tag() + " validation"
}
ctx.StopWithProblem(iris.StatusBadRequest, iris.NewProblem().
Title("Validation Error").
Detail("One or more fields failed validation").
Key("errors", errors))
return
}
}
ctx.JSON(iris.Map{
"message": "User validated successfully",
"user": user,
})
})
app.Listen(":8080")
}
Custom Validation
go
type Registration struct {
Username string `json:"username" validate:"required,min=3"`
Email string `json:"email" validate:"required,email"`
Password string `json:"password" validate:"required,min=8"`
ConfirmPassword string `json:"confirm_password" validate:"required,eqfield=Password"`
}
func passwordsMatch(fl validator.FieldLevel) bool {
return fl.Field().String() == fl.Parent().FieldByName("Password").String()
}
func main() {
app := iris.New()
validate := validator.New()
// Register custom validation
validate.RegisterValidation("passwords_match", passwordsMatch)
app.Post("/register", func(ctx iris.Context) {
var reg Registration
if err := ctx.ReadJSON(®); err != nil {
ctx.StopWithError(iris.StatusBadRequest, err)
return
}
if err := validate.Struct(reg); err != nil {
ctx.StopWithProblem(iris.StatusBadRequest, iris.NewProblem().
Title("Validation Error").
DetailErr(err))
return
}
ctx.JSON(iris.Map{
"message": "Registration successful",
})
})
app.Listen(":8080")
}
Cross-Field Validation
go
type DateRange struct {
Start time.Time `json:"start" validate:"required"`
End time.Time `json:"end" validate:"required,gtfield=Start"`
}
app.Post("/daterange", func(ctx iris.Context) {
var dates DateRange
if err := ctx.ReadJSON(&dates); err != nil {
ctx.StopWithError(iris.StatusBadRequest, err)
return
}
if err := validate.Struct(dates); err != nil {
ctx.StopWithProblem(iris.StatusBadRequest, iris.NewProblem().
Title("Validation Error").
DetailErr(err))
return
}
ctx.JSON(iris.Map{
"message": "Date range is valid",
"dates": dates,
})
})
Best Practices
Validation Rules:
- Use descriptive tags
- Implement custom rules
- Handle cross-field validation
- Document requirements
- Test edge cases
Error Handling:
- Provide clear messages
- Return proper status codes
- Log validation errors
- Handle all cases
- Document errors
Security:
- Validate all input
- Set proper limits
- Handle special characters
- Monitor validation
- Prevent injection
Performance:
- Cache validator
- Optimize rules
- Handle timeouts
- Monitor performance
- Clean resources