I see that we can use c.bindJSON()
to attach incoming request bodies to predefined structs. This method also validates the body in the process, which is great.
I am wondering if I can have a standalone middleware that validates incoming request bodies using c.bindJSON()
AND send the bound&verified body to the handler. This way I can write one single validate middleware for different requests with different structs.
Comment From: ljluestc
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"net/http"
)
// Define a struct to hold the data we expect in the request body
type MyRequest struct {
Name string `json:"name" binding:"required"`
Email string `json:"email" binding:"required,email"`
}
// Custom middleware that binds and validates the JSON body
func BindAndValidateJSON() gin.HandlerFunc {
return func(c *gin.Context) {
var jsonBody MyRequest
// Bind the incoming JSON request body to the struct
if err := c.ShouldBindJSON(&jsonBody); err != nil {
// If binding or validation fails, send a 400 response with the error
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
c.Abort()
return
}
// If binding and validation succeed, store the result in the context
c.Set("validatedBody", jsonBody)
c.Next() // Continue to the next handler
}
}
func main() {
r := gin.Default()
// Apply the custom middleware on a route
r.POST("/validate", BindAndValidateJSON(), func(c *gin.Context) {
// Retrieve the validated body from the context
validatedBody, exists := c.Get("validatedBody")
if !exists {
c.JSON(http.StatusInternalServerError, gin.H{"error": "No validated body"})
return
}
// You can now use the validated body in your handler
c.JSON(http.StatusOK, gin.H{
"message": "Validation successful",
"data": validatedBody,
})
})
// Run the server
r.Run(":8080")
}