验证

原文: https://docs.gofiber.io/guide/validation

🔎 Validation 验证

Validator package Validator 包

Fiber can make great use of the validator package to ensure correct validation of data to store.

​ Fiber 可以充分利用 validator 包来确保要存储的数据的正确验证。

You can find the detailed descriptions of the validations used in the fields contained on the structs below:

​ 您可以在下面结构中包含的字段中找到所用验证的详细说明:

Validation Example 验证示例

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package main

import (
    "fmt"
    "log"
    "strings"

    "github.com/go-playground/validator/v10"
    "github.com/gofiber/fiber/v2"
)

type (
    User struct {
        Name string `validate:"required,min=5,max=20"` // Required field, min 5 char long max 20
        Age  int    `validate:"required,teener"`       // Required field, and client needs to implement our 'teener' tag format which we'll see later
    }

    ErrorResponse struct {
        Error       bool
        FailedField string
        Tag         string
        Value       interface{}
    }

    XValidator struct {
        validator *validator.Validate
    }

    GlobalErrorHandlerResp struct {
        Success bool   `json:"success"`
        Message string `json:"message"`
    }
)

// This is the validator instance
// for more information see: https://github.com/go-playground/validator
var validate = validator.New()

func (v XValidator) Validate(data interface{}) []ErrorResponse {
    validationErrors := []ErrorResponse{}

    errs := validate.Struct(data)
    if errs != nil {
        for _, err := range errs.(validator.ValidationErrors) {
            // In this case data object is actually holding the User struct
            var elem ErrorResponse

            elem.FailedField = err.Field() // Export struct field name
            elem.Tag = err.Tag()           // Export struct tag
            elem.Value = err.Value()       // Export field value
            elem.Error = true

            validationErrors = append(validationErrors, elem)
        }
    }

    return validationErrors
}

func main() {
    myValidator := &XValidator{
        validator: validate,
    }

    app := fiber.New(fiber.Config{
        // Global custom error handler
        ErrorHandler: func(c *fiber.Ctx, err error) error {
            return c.Status(fiber.StatusBadRequest).JSON(GlobalErrorHandlerResp{
                Success: false,
                Message: err.Error(),
            })
        },
    })

    // Custom struct validation tag format
    myValidator.validator.RegisterValidation("teener", func(fl validator.FieldLevel) bool {
        // User.Age needs to fit our needs, 12-18 years old.
        return fl.Field().Int() >= 12 && fl.Field().Int() <= 18
    })

    app.Get("/", func(c *fiber.Ctx) error {
        user := &User{
            Name: c.Query("name"),
            Age:  c.QueryInt("age"),
        }

        // Validation
        if errs := myValidator.Validate(user); len(errs) > 0 && errs[0].Error {
            errMsgs := make([]string, 0)

            for _, err := range errs {
                errMsgs = append(errMsgs, fmt.Sprintf(
                    "[%s]: '%v' | Needs to implement '%s'",
                    err.FailedField,
                    err.Value,
                    err.Tag,
                ))
            }

            return &fiber.Error{
                Code:    fiber.ErrBadRequest.Code,
                Message: strings.Join(errMsgs, " and "),
            }
        }

        // Logic, validated with success
        return c.SendString("Hello, World!")
    })

    log.Fatal(app.Listen(":3000"))
}

/**
OUTPUT

[1]
Request:

GET http://127.0.0.1:3000/

Response:

{"success":false,"message":"[Name]: '' | Needs to implement 'required' and [Age]: '0' | Needs to implement 'required'"}

[2]
Request:

GET http://127.0.0.1:3000/?name=efdal&age=9

Response:
{"success":false,"message":"[Age]: '9' | Needs to implement 'teener'"}

[3]
Request:

GET http://127.0.0.1:3000/?name=efdal&age=

Response:
{"success":false,"message":"[Age]: '0' | Needs to implement 'required'"}

[4]
Request:

GET http://127.0.0.1:3000/?name=efdal&age=18

Response:
Hello, World!

**/
最后修改 February 5, 2024: 更新 (f57b279)