ginvalidator

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 9, 2026 License: MIT Imports: 15 Imported by: 0

README

ginvalidator

CI Go Reference Go Report Card License

Middleware-based request validation for Gin. Chain validators, sanitizers and modifiers on any request field, then collect the errors however you want.

Inspired by express-validator. All built-in validators and sanitizers are powered by validatorgo.

Requirements

Install

go get github.com/bube054/ginvalidator

Getting Started

Let's build a small signup API together, step by step. By the end you'll know how to validate fields, read errors, sanitize input and access the cleaned-up data.

Step 1 — A bare Gin server

Create a new folder, run go mod init example.com/signup, then create main.go:

package main

import (
	"net/http"

	"github.com/gin-gonic/gin"
)

func main() {
	r := gin.Default()

	r.POST("/signup", func(ctx *gin.Context) {
		ctx.JSON(http.StatusOK, gin.H{"message": "welcome aboard"})
	})

	r.Run()
}

Run it:

go run main.go

The server is now listening on http://localhost:8080. Every time you change your code, you'll need to stop the server (Ctrl+C) and run go run main.go again. If that gets annoying, check out Air — it watches your files and restarts the server automatically on every save.

Now open a separate terminal and send a request:

curl -X POST http://localhost:8080/signup

Windows users: PowerShell's curl is actually an alias for Invoke-WebRequest — avoid it. Use Git Bash, WSL, or Command Prompt instead. Some curl commands in this guide use bash syntax (\ for line breaks, single quotes around JSON) that won't work in Command Prompt. Whenever that's the case, we'll show both the bash version and a Command Prompt version right below it. If you're new to curl, this guide is a good starting point.

You should see {"message":"welcome aboard"}. The route works, but it accepts literally anything — no validation at all. Let's fix that.

Step 2 — Adding validators

Install ginvalidator:

go get github.com/bube054/ginvalidator

Now update main.go to validate an email and a username field from the request body:

package main

import (
	"net/http"

	gv "github.com/bube054/ginvalidator"
	"github.com/gin-gonic/gin"
)

func main() {
	r := gin.Default()

	r.POST("/signup",
		gv.NewBodyChain("email", nil).
			Not().Empty(nil).
			Bail().
			Email(nil).
			Validate(),
		gv.NewBodyChain("username", nil).
			Not().Empty(nil).
			Bail().
			Alphanumeric(nil).
			Validate(),
		func(ctx *gin.Context) {
			ctx.JSON(http.StatusOK, gin.H{"message": "welcome aboard"})
		},
	)

	r.Run()
}

Let's unpack what's going on:

  • gv.NewBodyChain("email", nil) creates a validation chain for the "email" field in the request body. The second argument is an optional error formatter — nil means "use defaults".
  • .Not().Empty(nil) means "this field must not be empty". Empty checks if a string is empty, and Not() flips the result — so an empty string fails.
  • .Bail() tells the chain to stop if anything before it failed. Without this, the chain would keep going and run Email on an empty string, which would give you a second, redundant error.
  • .Email(nil) checks that the value is a valid email address.
  • .Validate() finishes the chain and returns a gin.HandlerFunc that you plug into the route.

Each chain is its own middleware. Gin runs them left to right before your handler.

Note: gv is used as an alias for ginvalidator throughout these examples. You'll also see vgo used as an alias for validatorgo later on.

Now restart the server (Ctrl+C, then go run main.go — or let Air handle it) and try a bad request:

curl -X POST http://localhost:8080/signup \
  -H "Content-Type: application/json" \
  -d '{"email": "nope", "username": ""}'

On Windows Command Prompt:

curl -X POST http://localhost:8080/signup ^
  -H "Content-Type: application/json" ^
  -d "{\"email\": \"nope\", \"username\": \"\"}"

Hmm, you still get {"message":"welcome aboard"}. Why? Because ginvalidator records errors but doesn't reject the request for you — that's your job. Let's handle the errors.

Step 3 — Checking for errors

Update the handler to check for validation errors before responding:

r.POST("/signup",
	gv.NewBodyChain("email", nil).
		Not().Empty(nil).
		Bail().
		Email(nil).
		Validate(),
	gv.NewBodyChain("username", nil).
		Not().Empty(nil).
		Bail().
		Alphanumeric(nil).
		Validate(),
	func(ctx *gin.Context) {
		result, err := gv.ValidationResult(ctx)
		if err != nil {
			ctx.IndentedJSON(http.StatusInternalServerError, gin.H{
				"error": "something went wrong",
			})
			ctx.Abort()
			return
		}

		if len(result) > 0 {
			ctx.IndentedJSON(http.StatusUnprocessableEntity, gin.H{
				"errors": result,
			})
			ctx.Abort()
			return
		}

		ctx.IndentedJSON(http.StatusOK, gin.H{"message": "welcome aboard"})
	},
)

ValidationResult(ctx) pulls every recorded error out of the Gin context and returns them as a sorted slice. If there are errors, we send them back. If not, we proceed.

Restart the server (Ctrl+C, then go run main.go — or let Air handle it) and try the same bad request:

curl -X POST http://localhost:8080/signup \
  -H "Content-Type: application/json" \
  -d '{"email": "nope", "username": ""}'

On Windows Command Prompt:

curl -X POST http://localhost:8080/signup ^
  -H "Content-Type: application/json" ^
  -d "{\"email\": \"nope\", \"username\": \"\"}"

Tip: For this example we're using ctx.IndentedJSON instead of ctx.JSON so the response comes back pretty-printed and easy to read.

Now you get:

{
  "errors": [
    {
      "location": "body",
      "message": "invalid email",
      "field": "email",
      "value": "nope",
      "code": "invalid_format"
    },
    {
      "location": "body",
      "message": "Invalid value",
      "field": "username",
      "value": ""
    }
  ]
}

Two errors, one for each field. Let's look at what each piece means:

  • email "nope": Not().Empty() passed (it's not empty), so the chain continued past Bail(). Then Email() failed — "nope" isn't a valid email. The message ("invalid email") and code ("invalid_format") were provided automatically by validatorgo.
  • username "": Not().Empty() failed — the string IS empty, and Not() flipped that into a failure. Bail() stopped the chain right there, so Alphanumeric never ran. Since Empty technically passed before Not() negated it, there's no validatorgo error message to use, so it falls back to "Invalid value".

Try a valid request now:

curl -X POST http://localhost:8080/signup \
  -H "Content-Type: application/json" \
  -d '{"email": "[email protected]", "username": "john123"}'

On Windows Command Prompt:

curl -X POST http://localhost:8080/signup ^
  -H "Content-Type: application/json" ^
  -d "{\"email\": \"[email protected]\", \"username\": \"john123\"}"

{"message":"welcome aboard"} — it works!

Step 4 — Better error messages

That "Invalid value" for the username isn't very helpful. Let's write a custom error formatter. It's a function you pass as the second argument to NewBodyChain:

gv.NewBodyChain("username",
	func(initialValue, sanitizedValue, validatorName string) string {
		switch validatorName {
		case gv.EmptyValidatorName:
			return "Username can't be blank."
		case gv.AlphanumericValidatorName:
			return "Username can only contain letters and numbers."
		default:
			return "Invalid username."
		}
	},
).
	Not().Empty(nil).
	Bail().
	Alphanumeric(nil).
	Validate()

The function receives three things:

  • initialValue — the original value from the request
  • sanitizedValue — the value after any sanitizers have run (more on this later)
  • validatorName — which validator failed, e.g. "Empty", "Email", "Alphanumeric"

You can use validatorName to return different messages for different failures on the same field. The full list of validator names is in the ginvalidator constants.

Step 5 — Sanitizing input

Validation tells you if the data is good. Sanitization cleans the data up.

Right now, a user could send something like <script>alert('hacked')</script> as a username. If you ever render that in HTML, you've got a Cross-Site Scripting (XSS) vulnerability. The Escape sanitizer fixes this by converting special HTML characters into safe equivalents (e.g. < becomes &lt;):

gv.NewBodyChain("username", nil).
	Trim("").
	Not().Empty(nil).
	Escape().          // HTML-escape to prevent XSS
	Validate()

Try it — send a script tag as the username:

curl -X POST http://localhost:8080/signup \
  -H "Content-Type: application/json" \
  -d '{"email": "[email protected]", "username": "<script>alert(1)</script>"}'

On Windows Command Prompt (< and > are redirection operators in cmd, so they need to be escaped with ^):

curl -X POST http://localhost:8080/signup ^
  -H "Content-Type: application/json" ^
  -d "{\"email\": \"[email protected]\", \"username\": \"^<script^>alert(1)^</script^>\"}"

You'll get {"message":"welcome aboard"} — the username isn't empty, so it passes. But behind the scenes, Escape transformed the value into &lt;script&gt;alert(1)&lt;&#x2F;script&gt; before storing it. We'll see the actual sanitized value in the next step when we read matched data.

We also added Trim before the empty check. Order matters here — if someone sends " " (just spaces), we want to strip those first, then check if it's empty. If we did it the other way around, " " would pass the empty check and we'd end up with an empty username.

Important: Sanitizers don't modify the original http.Request. To access the sanitized value, you need to use GetMatchedData — we'll do that next.

Step 6 — Reading the validated data

After validation and sanitization, ginvalidator stores the final values for you. Pull them out with GetMatchedData:

r.POST("/signup",
	gv.NewBodyChain("email", nil).
		Not().Empty(nil).
		Bail().
		Email(nil).
		Validate(),
	gv.NewBodyChain("username", nil).
		Trim("").
		Not().Empty(nil).
		Escape().
		Validate(),
	func(ctx *gin.Context) {
		result, err := gv.ValidationResult(ctx)
		if err != nil {
			ctx.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{
				"error": "something went wrong",
			})
			return
		}

		if len(result) > 0 {
			ctx.AbortWithStatusJSON(http.StatusUnprocessableEntity, gin.H{
				"errors": result,
			})
			return
		}

		data, err := gv.GetMatchedData(ctx)
		if err != nil {
			ctx.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{
				"error": "something went wrong",
			})
			return
		}

		email, _ := data.Get(gv.BodyLocation, "email")
		username, _ := data.Get(gv.BodyLocation, "username")

		// email and username are validated + sanitized, safe to use
		ctx.JSON(http.StatusOK, gin.H{
			"message":  "welcome aboard",
			"email":    email,
			"username": username,
		})
	},
)

data.Get(location, fieldName) returns the final value and a boolean. The first argument is the location constant — BodyLocation, QueryLocation, ParamLocation, HeaderLocation, or CookieLocation — and the second is the field name.

That's the core loop: create chainscheck errorsread matched data. Everything else builds on this.


Validation chains in depth

We've been using NewBodyChain so far. There are five of these, one for each place data can come from in an HTTP request:

Constructor Location constant Reads from
NewBodyChain BodyLocation Request body (JSON, form, multipart)
NewQueryChain QueryLocation URL query parameters
NewParamChain ParamLocation Gin route parameters (:id)
NewHeaderChain HeaderLocation HTTP headers
NewCookieChain CookieLocation Cookies

They all work the same way — the only difference is where they look for the field value.

Just a shortcut: Each NewXChain is shorthand for NewX(...).Chain(). So NewBodyChain("email", nil) is the same as NewBody("email", nil).Chain(), NewQueryChain("q", nil) is the same as NewQuery("q", nil).Chain(), and so on for NewParam, NewHeader and NewCookie. The longer form is still there if you ever need to hold on to the intermediate value.

A few things worth knowing about field names:

  • JSON body fields use GJSON path syntax — so for {"user":{"profile":{"email":"[email protected]"}}}, the field name is "user.profile.email". You're not limited to top-level keys.
  • Body extraction switches on Content-Type — JSON uses GJSON paths, while application/x-www-form-urlencoded and multipart/form-data use plain form field names.
  • Headers must be in canonical form — use "Content-Type", not "content-type". ginvalidator will log a warning if you pass a non-canonical key.

Here's a route that validates a route parameter and an optional query parameter:

r.GET("/users/:id",
	gv.NewParamChain("id", nil).
		Not().Empty(nil).
		Bail().
		Numeric(nil).
		Validate(),
	gv.NewQueryChain("fields", nil).
		Optional().
		Alpha(nil).
		Validate(),
	func(ctx *gin.Context) {
		result, err := gv.ValidationResult(ctx)
		if err != nil {
			ctx.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{
				"error": "something went wrong",
			})
			return
		}

		if len(result) > 0 {
			ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errors": result})
			return
		}

		data, _ := gv.GetMatchedData(ctx)
		id, _ := data.Get(gv.ParamLocation, "id")
		ctx.JSON(http.StatusOK, gin.H{"user_id": id})
	},
)

Try it out — these GET requests work the same in bash and Command Prompt:

# valid: numeric id, alpha fields
curl http://localhost:8080/users/123?fields=name

# valid: numeric id, fields omitted (Optional skips the chain)
curl http://localhost:8080/users/123

# invalid: non-numeric id
curl http://localhost:8080/users/abc

# invalid: fields contains digits
curl http://localhost:8080/users/123?fields=name1
Reusing chains

If you use the same validation in multiple places, wrap it in a function:

func validateEmail() gin.HandlerFunc {
	return gv.NewBodyChain("email", nil).
		Not().Empty(nil).
		Bail().
		Email(nil).
		Validate()
}

r.POST("/login", validateEmail(), loginHandler)
r.POST("/signup", validateEmail(), signupHandler)

Validators

Validators check if a field value meets some criteria. When one fails, an error is recorded. It doesn't reject the request — you decide what to do with the errors in your handler.

All built-in validators are powered by validatorgo — my other open source library that I originally built for this very project. ginvalidator wraps each one as a chain method: validatorgo's IsEmail becomes .Email(), IsAlphanumeric becomes .Alphanumeric(), IsEmpty becomes .Empty(), and so on (the Is prefix is dropped).

Here are some commonly used ones:

  • Email, URL, IP, UUID — format checks
  • Alpha, Alphanumeric, Numeric, Int, Float — character/number checks
  • Empty, Contains, Equals, Matches — string checks
  • CreditCard, MobilePhone, PostalCode — domain-specific checks
  • StrongPassword — password strength
  • JSON, Boolean, Date, ISO8601 — data type checks

The full list is in the ginvalidator constants. For detailed documentation on what each validator does and its options, see validatorgo on pkg.go.dev.

Validator options

Many validators accept an options struct to tweak their behavior. These structs come from validatorgo. Pass nil when the defaults are fine (which is most of the time):

gv.NewBodyChain("email", nil).
	Email(nil).
	Validate()

When you need to customize, import validatorgo and pass the struct. Note that these structs use pointer types (*bool, *int, *string) so the library can tell the difference between "not set" and "set to the zero value" — see validatorgo's option fields docs for the full rationale:

import vgo "github.com/bube054/validatorgo"

gv.NewBodyChain("email", nil).
	Email(&vgo.IsEmailOpts{
		RequireTld:    vgo.Bool(false), // helper from validatorgo to create a *bool pointer
		HostWhitelist: []string{"gmail.com", "yahoo.com"},
	}).
	Validate()

validatorgo provides little helpers like vgo.Bool, vgo.String, vgo.Int and vgo.Float64 that take a value and return a pointer to it — so you don't have to declare an intermediate variable just to take its address. If you use validatorgo structs directly in your code, run go mod tidy so Go adds it as a direct dependency.

CustomValidator

For logic that built-in validators can't cover — like checking if an email is already taken:

// pretend this hits a database
func userExistsByEmail(email string) bool {
	taken := map[string]bool{"[email protected]": true}
	return taken[email]
}

r.POST("/create-user",
	gv.NewBodyChain("email", nil).
		Not().Empty(nil).
		Bail().
		Email(nil).
		CustomValidator(func(r *http.Request, initialValue, sanitizedValue string) bool {
			return !userExistsByEmail(sanitizedValue)
		}).
		Validate(),
	func(ctx *gin.Context) {
		result, _ := gv.ValidationResult(ctx)
		if len(result) > 0 {
			ctx.AbortWithStatusJSON(http.StatusConflict, gin.H{"errors": result})
			return
		}
		ctx.JSON(http.StatusCreated, gin.H{"message": "user created"})
	},
)

Try it:

# fresh email → passes
curl -X POST http://localhost:8080/create-user \
  -H "Content-Type: application/json" \
  -d '{"email": "[email protected]"}'
# {"message":"user created"}

# email already taken → CustomValidator returns false
curl -X POST http://localhost:8080/create-user \
  -H "Content-Type: application/json" \
  -d '{"email": "[email protected]"}'

The function signature:

type CustomValidatorFunc func(r *http.Request, initialValue, sanitizedValue string) bool
  • r — the raw HTTP request
  • initialValue — the value before any sanitization
  • sanitizedValue — the value after sanitizers that ran earlier in the chain
  • Return true if valid, false if not

CustomValidator doesn't produce error codes (since there's no validatorgo validator behind it).

Sanitizers

Sanitizers transform the field value. The transformed value is what later validators in the chain see, and what you get back from GetMatchedData.

Built-in sanitizers (also from validatorgo):

Trim, LTrim, RTrim, Escape, Unescape, Blacklist, Whitelist, NormalizeEmail, StripLow, ToBoolean, ToDate, ToFloat, ToInt

We already saw Trim and Escape in the Getting Started section. Here's another example — normalizing an email address:

r.POST("/subscribe",
	gv.NewBodyChain("email", nil).
		Trim("").
		NormalizeEmail(nil).
		Not().Empty(nil).
		Bail().
		Email(nil).
		Validate(),
	func(ctx *gin.Context) {
		result, _ := gv.ValidationResult(ctx)
		if len(result) > 0 {
			ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errors": result})
			return
		}

		data, _ := gv.GetMatchedData(ctx)
		email, _ := data.Get(gv.BodyLocation, "email")
		// email is trimmed + normalized (e.g. "[email protected]" → "[email protected]")

		ctx.JSON(http.StatusOK, gin.H{"subscribed": email})
	},
)

Try it with a messy email:

curl -X POST http://localhost:8080/subscribe \
  -H "Content-Type: application/json" \
  -d '{"email": "  [email protected]  "}'

On Windows Command Prompt:

curl -X POST http://localhost:8080/subscribe ^
  -H "Content-Type: application/json" ^
  -d "{\"email\": \"  [email protected]  \"}"

You'll get back:

{"subscribed":"[email protected]"}

The whitespace was trimmed and the email was normalized to lowercase before being stored.

Remember: Sanitizers don't modify the original http.Request. Always use GetMatchedData to read sanitized values.

CustomSanitizer
type CustomSanitizerFunc func(r *http.Request, initialValue, sanitizedValue string) string

Whatever string you return becomes the new value:

r.POST("/articles",
	gv.NewBodyChain("slug", nil).
		CustomSanitizer(func(r *http.Request, initialValue, sanitizedValue string) string {
			return strings.ToLower(strings.ReplaceAll(sanitizedValue, " ", "-"))
		}).
		Validate(),
	func(ctx *gin.Context) {
		data, _ := gv.GetMatchedData(ctx)
		slug, _ := data.Get(gv.BodyLocation, "slug")
		ctx.JSON(http.StatusOK, gin.H{"slug": slug})
	},
)

Try it:

curl -X POST http://localhost:8080/articles \
  -H "Content-Type: application/json" \
  -d '{"slug": "My Blog Post"}'
# {"slug":"my-blog-post"}

Modifiers

Modifiers don't validate or transform — they control how the chain behaves.

Not

Negates the next validator. A pass becomes a fail, a fail becomes a pass.

// "this field must NOT be empty"
r.POST("/check-name",
	gv.NewBodyChain("name", nil).
		Not().Empty(nil).
		Validate(),
	func(ctx *gin.Context) {
		if gv.HasErrors(ctx) {
			ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "name is required"})
			return
		}
		ctx.JSON(http.StatusOK, gin.H{"message": "ok"})
	},
)

Try it:

# empty name → fails
curl -X POST http://localhost:8080/check-name \
  -H "Content-Type: application/json" \
  -d '{"name": ""}'
# {"error":"name is required"}

# non-empty name → passes
curl -X POST http://localhost:8080/check-name \
  -H "Content-Type: application/json" \
  -d '{"name": "alice"}'
# {"message":"ok"}

Step by step: Empty checks if the string is empty. If the string IS empty, Empty returns true ("yes it's empty"). Not() flips that to false — validation fails. If the string is NOT empty, Empty returns false, Not() flips it to true — validation passes.

Not() only affects the single validator right after it.

Bail

Stops the chain if any previous validator failed. Put it after any validator where continuing doesn't make sense:

r.POST("/transfer",
	gv.NewBodyChain("amount", nil).
		Not().Empty(nil).
		Bail().              // stop if empty
		Numeric(nil).
		Bail().              // stop if not numeric
		CustomValidator(func(r *http.Request, initialValue, sanitizedValue string) bool {
			// no point hitting the DB if the value isn't even a number
			return sanitizedValue == "100" // pretend only 100 is affordable
		}).
		Validate(),
	func(ctx *gin.Context) {
		if gv.HasErrors(ctx) {
			result, _ := gv.ValidationResult(ctx)
			ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errors": result})
			return
		}
		ctx.JSON(http.StatusOK, gin.H{"message": "transferred"})
	},
)

Try it:

# empty → first Bail stops the chain. only one error.
curl -X POST http://localhost:8080/transfer \
  -H "Content-Type: application/json" \
  -d '{"amount": ""}'

# not numeric → passes Empty, fails Numeric. second Bail stops the chain.
curl -X POST http://localhost:8080/transfer \
  -H "Content-Type: application/json" \
  -d '{"amount": "abc"}'

# numeric but insufficient → all the way to CustomValidator.
curl -X POST http://localhost:8080/transfer \
  -H "Content-Type: application/json" \
  -d '{"amount": "50"}'

# happy path
curl -X POST http://localhost:8080/transfer \
  -H "Content-Type: application/json" \
  -d '{"amount": "100"}'
# {"message":"transferred"}

Without Bail(), every validator would run on every request, and you'd get errors stacked up (plus you'd hit the DB even when the value isn't a number). You can use Bail() multiple times in the same chain.

Optional

Skips the entire chain if the field is empty. You can put it anywhere in the chain — position doesn't matter.

// bio is optional — if empty, no validators run.
// if the user does send a value, it must be alpha characters only.
r.POST("/profile",
	gv.NewBodyChain("bio", nil).
		Optional().
		Alpha(nil).
		Validate(),
	func(ctx *gin.Context) {
		if gv.HasErrors(ctx) {
			result, _ := gv.ValidationResult(ctx)
			ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errors": result})
			return
		}
		ctx.JSON(http.StatusOK, gin.H{"message": "saved"})
	},
)

Try it:

# bio omitted → Optional skips the chain → passes
curl -X POST http://localhost:8080/profile \
  -H "Content-Type: application/json" \
  -d '{}'
# {"message":"saved"}

# bio is alpha → passes
curl -X POST http://localhost:8080/profile \
  -H "Content-Type: application/json" \
  -d '{"bio": "hello"}'
# {"message":"saved"}

# bio has digits → Alpha fails
curl -X POST http://localhost:8080/profile \
  -H "Content-Type: application/json" \
  -d '{"bio": "hello123"}'
If

Conditionally stops the chain based on a function you provide. Return true to stop (bail out), false to continue.

type IfModifierFunc func(r *http.Request, initialValue, sanitizedValue string) bool
// only validate the discount code if the user is a premium member
r.POST("/checkout",
	gv.NewBodyChain("discountCode", nil).
		If(func(r *http.Request, initialValue, sanitizedValue string) bool {
			// return true = stop the chain, false = keep going
			return r.Header.Get("X-User-Tier") != "premium"
		}).
		Not().Empty(nil).
		Bail().
		Alphanumeric(nil).
		Validate(),
	func(ctx *gin.Context) {
		if gv.HasErrors(ctx) {
			result, _ := gv.ValidationResult(ctx)
			ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errors": result})
			return
		}
		ctx.JSON(http.StatusOK, gin.H{"message": "checked out"})
	},
)

Try it:

# no premium header → If returns true → chain stops → empty discount is fine
curl -X POST http://localhost:8080/checkout \
  -H "Content-Type: application/json" \
  -d '{"discountCode": ""}'
# {"message":"checked out"}

# premium user with empty code → If returns false → validators run → fails
curl -X POST http://localhost:8080/checkout \
  -H "Content-Type: application/json" \
  -H "X-User-Tier: premium" \
  -d '{"discountCode": ""}'

# premium user with valid code → passes
curl -X POST http://localhost:8080/checkout \
  -H "Content-Type: application/json" \
  -H "X-User-Tier: premium" \
  -d '{"discountCode": "SAVE20"}'
# {"message":"checked out"}

If If returns true, the chain stops right there — no validators after it run, no errors recorded.

Skip

Skips just the next item in the chain (validator, sanitizer, or modifier). Return true to skip it, false to run it.

type SkipModifierFunc func(r *http.Request, initialValue, sanitizedValue string) bool
// skip the length check when the request comes from an admin
r.POST("/post-message",
	gv.NewBodyChain("message", nil).
		Not().Empty(nil).
		Skip(func(r *http.Request, initialValue, sanitizedValue string) bool {
			return r.Header.Get("X-Role") == "admin"
		}).
		ByteLength(&vgo.IsByteLengthOpts{Max: vgo.Int(10)}). // skipped if Skip returned true
		Validate(),
	func(ctx *gin.Context) {
		if gv.HasErrors(ctx) {
			result, _ := gv.ValidationResult(ctx)
			ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errors": result})
			return
		}
		ctx.JSON(http.StatusOK, gin.H{"message": "posted"})
	},
)

Try it:

# regular user with short message → passes
curl -X POST http://localhost:8080/post-message \
  -H "Content-Type: application/json" \
  -d '{"message": "hello"}'
# {"message":"posted"}

# regular user with long message → fails ByteLength
curl -X POST http://localhost:8080/post-message \
  -H "Content-Type: application/json" \
  -d '{"message": "this message is way too long"}'

# admin with the same long message → ByteLength is skipped → passes
curl -X POST http://localhost:8080/post-message \
  -H "Content-Type: application/json" \
  -H "X-Role: admin" \
  -d '{"message": "this message is way too long"}'
# {"message":"posted"}

Unlike If, Skip only skips the next item — everything after it still runs.

Error messages

When a validator fails, ginvalidator picks the error message using this priority:

  1. Per-chain formatter — the function you pass as the second argument to NewBodyChain, NewQueryChain, etc. (we covered this in Step 4)
  2. DefaultErrFmtFunc — a package-level formatter you can set once for your whole app
  3. validatorgo message — the validatorgo validator returns a ValidationError with a Message field (like "invalid email"). If nothing above is set, this is used.
  4. "Invalid value" — the last-resort fallback
DefaultErrFmtFunc

If you're tired of writing formatters for every single chain, set a global default. It applies to any chain that doesn't have its own formatter:

func main() {
	gv.DefaultErrFmtFunc = func(initialValue, sanitizedValue, validatorName string) string {
		return fmt.Sprintf("%s check failed", validatorName)
	}

	r := gin.Default()
	// ... all your routes will use this formatter as the default
	r.Run()
}

Per-chain formatters still win when present.

Error codes

You may have noticed the code field in some of the error responses earlier. When a built-in validator fails, validatorgo returns a ValidationError that looks like this:

// from validatorgo
type ValidationError struct {
	Validator string // e.g. "IsEmail"
	Code      string // e.g. "invalid_format"
	Message   string // e.g. "invalid email"
}

ginvalidator reads the Code and Message from this error and puts them into your validation results. The code field is omitempty in JSON, so it only shows up when there's actually a code. CustomValidator doesn't produce codes since there's no validatorgo validator behind it.

Understanding validatorgo's error types will help you make the most of these codes — they're handy for i18n or building client-side error handling.

Reading errors

We've been using ValidationResult to get all errors as a slice. That works, but ginvalidator also has helpers for common patterns.

For the examples below, assume each handler is plugged into a route like this so you have something to curl against:

r.POST("/signup",
	gv.NewBodyChain("email", nil).
		Not().Empty(nil).
		Bail().
		Email(nil).
		Validate(),
	gv.NewBodyChain("username", nil).
		Not().Empty(nil).
		Bail().
		Alphanumeric(nil).
		Validate(),
	signupHandler, // <-- swap in the handler from each example below
)

And the bad request we'll use to trigger errors:

curl -X POST http://localhost:8080/signup \
  -H "Content-Type: application/json" \
  -d '{"email": "nope", "username": ""}'
HasErrors

The simplest check — just a boolean:

func signupHandler(ctx *gin.Context) {
	if gv.HasErrors(ctx) {
		ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
			"error": "validation failed",
		})
		return
	}

	// all good, do your thing
	ctx.JSON(http.StatusCreated, gin.H{"message": "signed up"})
}

Response:

{"error":"validation failed"}
FirstError

When you only want to show one error at a time:

func signupHandler(ctx *gin.Context) {
	if err := gv.FirstError(ctx); err != nil {
		ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
			"field":   err.Field,
			"message": err.Message,
		})
		return
	}

	ctx.JSON(http.StatusCreated, gin.H{"message": "signed up"})
}

Response (only the first error — the email one):

{"field":"email","message":"invalid email"}

FirstError returns a pointer to the first ValidationChainError, or nil if everything passed.

ErrorsByField

Groups all errors by field name — useful when your UI shows a list of errors under each form input:

func signupHandler(ctx *gin.Context) {
	grouped, err := gv.ErrorsByField(ctx)
	if err != nil {
		ctx.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{
			"error": "something went wrong",
		})
		return
	}

	if len(grouped) > 0 {
		ctx.AbortWithStatusJSON(http.StatusUnprocessableEntity, gin.H{"errors": grouped})
		return
	}

	ctx.JSON(http.StatusCreated, gin.H{"message": "signed up"})
}

Response:

{
  "errors": {
    "email": [
      {"location":"body","message":"invalid email","field":"email","value":"nope","code":"invalid_format"}
    ],
    "username": [
      {"location":"body","message":"Invalid value","field":"username","value":""}
    ]
  }
}
FirstErrorByField

Same idea, but at most one error per field. Common for "show one error per input" UIs:

func signupHandler(ctx *gin.Context) {
	firsts, err := gv.FirstErrorByField(ctx)
	if err != nil {
		ctx.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{
			"error": "something went wrong",
		})
		return
	}

	if len(firsts) > 0 {
		ctx.AbortWithStatusJSON(http.StatusUnprocessableEntity, gin.H{"errors": firsts})
		return
	}

	ctx.JSON(http.StatusCreated, gin.H{"message": "signed up"})
}

Response (note each field maps to a single error object, not an array):

{
  "errors": {
    "email":    {"location":"body","message":"invalid email","field":"email","value":"nope","code":"invalid_format"},
    "username": {"location":"body","message":"Invalid value","field":"username","value":""}
  }
}

Matched data

We covered GetMatchedData in Step 6, but here's a quick recap of the two methods it gives you:

Get(location, field) — returns the value and a boolean:

data, _ := gv.GetMatchedData(ctx)
email, ok := data.Get(gv.BodyLocation, "email")
if !ok {
	// field wasn't matched
}

Has(location, field) — just checks if the field was matched, without pulling the value. Useful for optional fields:

if data.Has(gv.BodyLocation, "bio") {
	bio, _ := data.Get(gv.BodyLocation, "bio")
	// user sent a bio, do something with it
}

OneOf

Sometimes a request is valid if any one of several groups of validations passes. A login that accepts either an email or a phone number is a classic example:

r.POST("/login",
	gv.OneOf(
		[]gv.ValidationChain{
			gv.NewBodyChain("email", nil).
				Not().Empty(nil).
				Email(nil),
		},
		[]gv.ValidationChain{
			gv.NewBodyChain("phone", nil).
				Not().Empty(nil).
				MobilePhone(nil, ""),
		},
	),
	func(ctx *gin.Context) {
		if gv.HasErrors(ctx) {
			ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
				"error": "provide either a valid email or phone number",
			})
			return
		}

		data, _ := gv.GetMatchedData(ctx)
		if data.Has(gv.BodyLocation, "email") {
			email, _ := data.Get(gv.BodyLocation, "email")
			ctx.JSON(http.StatusOK, gin.H{"login_via": "email", "value": email})
			return
		}
		phone, _ := data.Get(gv.BodyLocation, "phone")
		ctx.JSON(http.StatusOK, gin.H{"login_via": "phone", "value": phone})
	},
)

If at least one group produces zero errors, the request passes and that group's matched data is saved. If every group fails, a single error with field "_oneOf" is recorded.

You can put multiple chains in one group — they all have to pass for that group to count:

gv.OneOf(
	// group 1: both name and email must be valid
	[]gv.ValidationChain{
		gv.NewBodyChain("name", nil).
			Not().Empty(nil),
		gv.NewBodyChain("email", nil).
			Not().Empty(nil).
			Email(nil),
	},
	// group 2: just a username
	[]gv.ValidationChain{
		gv.NewBodyChain("username", nil).
			Not().Empty(nil).
			Alphanumeric(nil),
	},
)

CheckSchema

When a route has a lot of fields, writing individual chains for each one gets long. CheckSchema lets you define everything in a single map and gives you back one middleware:

r.POST("/register",
	gv.CheckSchema(gv.Schema{
		"email": {
			In: gv.BodyLocation,
			Build: func(vc gv.ValidationChain) gv.ValidationChain {
				return vc.Not().Empty(nil).Bail().Email(nil)
			},
		},
		"username": {
			In: gv.BodyLocation,
			Build: func(vc gv.ValidationChain) gv.ValidationChain {
				return vc.Not().Empty(nil).Bail().Alphanumeric(nil)
			},
		},
		"bio": {
			In:       gv.BodyLocation,
			Optional: true,
			Build: func(vc gv.ValidationChain) gv.ValidationChain {
				return vc.Trim("").Escape()
			},
		},
	}),
	func(ctx *gin.Context) {
		if gv.HasErrors(ctx) {
			result, _ := gv.ValidationResult(ctx)
			ctx.AbortWithStatusJSON(http.StatusUnprocessableEntity, gin.H{"errors": result})
			return
		}

		ctx.JSON(http.StatusCreated, gin.H{"message": "registered"})
	},
)

Try it:

# all good — bio is optional and gets escaped
curl -X POST http://localhost:8080/register \
  -H "Content-Type: application/json" \
  -d '{"email": "[email protected]", "username": "jane123", "bio": "hi there"}'
# {"message":"registered"}

# bio omitted — Optional skips its chain, no errors
curl -X POST http://localhost:8080/register \
  -H "Content-Type: application/json" \
  -d '{"email": "[email protected]", "username": "jane123"}'
# {"message":"registered"}

# multiple things wrong — both email and username fail
curl -X POST http://localhost:8080/register \
  -H "Content-Type: application/json" \
  -d '{"email": "nope", "username": "jane!"}'

On Windows Command Prompt:

curl -X POST http://localhost:8080/register ^
  -H "Content-Type: application/json" ^
  -d "{\"email\": \"[email protected]\", \"username\": \"jane123\", \"bio\": \"hi there\"}"

Each field in the schema gets a SchemaField:

  • In — where the field comes from (BodyLocation, QueryLocation, ParamLocation, HeaderLocation, CookieLocation)
  • Optional — if true, skip validation when the field is empty
  • ErrFmtFunc — per-field error formatter (same type as the second argument to NewBodyChain)
  • Build — receives a fresh ValidationChain, return it with your validators/sanitizers/modifiers attached. Use Bail() inside Build to stop on first failure. If Build is nil, the field always passes.

Fields are processed in alphabetical order, so errors come back in a predictable order.

Maintainers

  • bube054Attah Gbubemi David (author)

License

MIT

Documentation

Overview

Package ginvalidator is a set of Gin middlewares that wraps the extensive collection of validators and sanitizers offered by validatorgo.

It allows you to combine them in many ways so that you can validate and sanitize your express requests, and offers tools to determine if the request is valid or not, which data was matched according to your validators, and so on.

It is based on the popular js/express library express-validator

Index

Constants

View Source
const (
	BailModifierName     string = "Bail"
	IfModifierName       string = "If"
	NotModifierName      string = "Not"
	SkipModifierName     string = "Skip"
	OptionalModifierName string = "Optional"
)
View Source
const (
	CustomSanitizerName         string = "CustomSanitizer"
	BlacklistSanitizerName      string = "Blacklist"
	EscapeSanitizerName         string = "Escape"
	LTrimSanitizerName          string = "LTrim"
	NormalizeEmailSanitizerName string = "NormalizeEmail"
	RTrimSanitizerName          string = "RTrim"
	StripLowSanitizerName       string = "StripLow"
	ToBooleanSanitizerName      string = "ToBoolean"
	ToDateSanitizerName         string = "ToDate"
	ToFloatSanitizerName        string = "ToFloat"
	ToIntSanitizerName          string = "ToInt"
	TrimSanitizerName           string = "Trim"
	UnescapeSanitizerName       string = "Unescape"
	WhitelistSanitizerName      string = "Whitelist"
)
View Source
const (
	CustomValidatorName             string = "CustomValidator"
	ContainsValidatorName           string = "Contains"
	EqualsValidatorName             string = "Equals"
	AbaRoutingValidatorName         string = "AbaRouting"
	AfterValidatorName              string = "After"
	AlphaValidatorName              string = "Alpha"
	AlphanumericValidatorName       string = "Alphanumeric"
	ArrayValidatorName              string = "Array"
	AsciiValidatorName              string = "Ascii"
	BTCAddressValidatorName         string = "BTCAddress"
	Base32ValidatorName             string = "Base32"
	Base58ValidatorName             string = "Base58"
	Base64ValidatorName             string = "Base64"
	BeforeValidatorName             string = "Before"
	BicValidatorName                string = "Bic"
	BooleanValidatorName            string = "Boolean"
	ByteLengthValidatorName         string = "ByteLength"
	CountryCodeValidatorName        string = "CountryCode"
	CreditCardValidatorName         string = "CreditCard"
	CurrencyValidatorName           string = "Currency"
	DataURIValidatorName            string = "DataURI"
	DateValidatorName               string = "Date"
	DecimalValidatorName            string = "Decimal"
	DivisibleByValidatorName        string = "DivisibleBy"
	EANValidatorName                string = "EAN"
	EmailValidatorName              string = "Email"
	EmptyValidatorName              string = "Empty"
	EthereumAddressValidatorName    string = "EthereumAddress"
	FQDNValidatorName               string = "FQDN"
	FloatValidatorName              string = "Float"
	FreightContainerIDValidatorName string = "FreightContainerID"
	FullWidthValidatorName          string = "FullWidth"
	HSLValidatorName                string = "HSL"
	HalfWidthValidatorName          string = "HalfWidth"
	HashValidatorName               string = "Hash"
	HexColorValidatorName           string = "HexColor"
	HexadecimalValidatorName        string = "Hexadecimal"
	IBANValidatorName               string = "IBAN"
	IMEIValidatorName               string = "IMEI"
	IPValidatorName                 string = "IP"
	IPRangeValidatorName            string = "IPRange"
	ISBNValidatorName               string = "ISBN"
	ISINValidatorName               string = "ISIN"
	ISO31661Alpha2ValidatorName     string = "ISO31661Alpha2"
	ISO31661Alpha3ValidatorName     string = "ISO31661Alpha3"
	ISO31661NumericValidatorName    string = "ISO31661Numeric"
	ISO6346ValidatorName            string = "ISO6346"
	ISO6391ValidatorName            string = "ISO6391"
	ISO8601ValidatorName            string = "ISO8601"
	ISRCValidatorName               string = "ISRC"
	ISSNValidatorName               string = "ISSN"
	IdentityCardValidatorName       string = "IdentityCard"
	InValidatorName                 string = "In"
	IntValidatorName                string = "Int"
	ISO4217ValidatorName            string = "ISO4217"
	JSONValidatorName               string = "JSON"
	JWTValidatorName                string = "JWT"
	LatLongValidatorName            string = "LatLong"
	LengthValidatorName             string = "Length"
	LicensePlateValidatorName       string = "LicensePlate"
	LocaleValidatorName             string = "Locale"
	LowerCaseValidatorName          string = "LowerCase"
	LuhnNumberValidatorName         string = "LuhnNumber"
	MD5ValidatorName                string = "MD5"
	MacAddressValidatorName         string = "MacAddress"
	MagnetURIValidatorName          string = "MagnetURI"
	MailtoURIValidatorName          string = "MailtoURI"
	MimeTypeValidatorName           string = "MimeType"
	MobilePhoneValidatorName        string = "MobilePhone"
	MongoIDValidatorName            string = "MongoID"
	MultibyteValidatorName          string = "Multibyte"
	NumericValidatorName            string = "Numeric"
	OctalValidatorName              string = "Octal"
	ObjectValidatorName             string = "Object"
	PassportNumberValidatorName     string = "PassportNumber"
	PortValidatorName               string = "Port"
	PostalCodeValidatorName         string = "PostalCode"
	RFC3339ValidatorName            string = "RFC3339"
	RgbColorValidatorName           string = "RgbColor"
	SemVerValidatorName             string = "SemVer"
	SlugValidatorName               string = "Slug"
	StrongPasswordValidatorName     string = "StrongPassword"
	SurrogatePairValidatorName      string = "SurrogatePair"
	TaxIDValidatorName              string = "TaxID"
	TimeValidatorName               string = "Time"
	ULIDValidatorName               string = "ULID"
	URLValidatorName                string = "URL"
	UUIDValidatorName               string = "UUID"
	UpperCaseValidatorName          string = "UpperCase"
	VATValidatorName                string = "VAT"
	VariableWidthValidatorName      string = "VariableWidth"
	WhitelistedValidatorName        string = "Whitelisted"
	MatchesValidatorName            string = "Matches"
)
View Source
const DefaultErrMsg string = "Invalid value"
View Source
const GinValidatorCtxErrorsStoreName string = "__ginvalidator__ctx__errors__"

GinValidatorCtxErrorsStoreName is the key, where the validation errors are stored.

View Source
const GinValidatorCtxMatchedDataStoreName string = "__ginvalidator__matched__data__"

Variables

View Source
var (
	// ErrNilCtxMatchedData is returned when a nil context is passed, preventing extraction of matched data.
	ErrNilCtxMatchedData = errors.New("nil context provided: unable to extract matched data")

	// ErrNoMatchedData is returned when no matched data is found in the context.
	ErrNoMatchedData = errors.New("no matched data available in context")
)
View Source
var (
	// ErrFieldExtractionFromNilCtx occurs when an operation attempts to extract a field from a nil Gin context.
	ErrFieldExtractionFromNilCtx = errors.New("failed to extract field: gin context is nil")

	// ErrExtractionInvalidContentType occurs when the request contains an unsupported or missing Content-Type header.
	ErrExtractionInvalidContentType = errors.New("failed to extract field: unsupported or missing Content-Type header")

	// ErrExtractionInvalidJSON occurs when JSON parsing fails due to malformed JSON in the request body.
	ErrExtractionInvalidJSON = errors.New("failed to extract field: invalid JSON in request body")
)
View Source
var (
	// ErrNilCtxValidationResult is returned when a nil context is provided, making it impossible to extract validation results.
	ErrNilCtxValidationResult = errors.New("nil context provided: unable to extract validation result")

	// ErrNoValidationResult is returned when no validation result is found in the context.
	ErrNoValidationResult = errors.New("validation result not found in context")
)

Functions

func CheckSchema added in v1.0.0

func CheckSchema(schema Schema) gin.HandlerFunc

CheckSchema creates a single gin.HandlerFunc from a declarative schema. Fields are processed in sorted order for deterministic error ordering.

Example:

router.POST("/register",
  ginvalidator.CheckSchema(ginvalidator.Schema{
    "email": {In: ginvalidator.BodyLocation, Build: func(vc ginvalidator.ValidationChain) ginvalidator.ValidationChain {
      return vc.Email(nil)
    }},
    "name": {In: ginvalidator.BodyLocation, Optional: true, Build: func(vc ginvalidator.ValidationChain) ginvalidator.ValidationChain {
      return vc.Alpha(nil)
    }},
  }),
  handler,
)

func ErrorsByField added in v1.0.0

func ErrorsByField(ctx *gin.Context) (map[string][]ValidationChainError, error)

ErrorsByField groups validation errors by field name.

func FirstErrorByField added in v1.0.0

func FirstErrorByField(ctx *gin.Context) (map[string]ValidationChainError, error)

FirstErrorByField returns at most one error per field.

func HasErrors added in v1.0.0

func HasErrors(ctx *gin.Context) bool

HasErrors returns true if there are any validation errors in the context.

func OneOf added in v1.0.0

func OneOf(chainGroups ...[]ValidationChain) gin.HandlerFunc

OneOf runs each group of validation chains and passes if at least one group produces no validation errors. If all groups fail, a single error is added to the context.

Each argument is a group of chains that must all pass together. The first group that passes wins — its matched data is saved and no errors are recorded.

Example:

router.POST("/login",
  ginvalidator.OneOf(
    []ginvalidator.ValidationChain{NewBody("email", nil).Chain().Email(nil)},
    []ginvalidator.ValidationChain{NewBody("phone", nil).Chain().MobilePhone(nil, "")},
  ),
  handler,
)

Types

type Body

type Body struct {
	// contains filtered or unexported fields
}

Body is used to validate data from the `http.Request` body.

func NewBody

func NewBody(field string, errFmtFunc ErrFmtFunc) Body

NewBody constructs a Body validator for the given field. Returns a Body object that can be used to create validation chains.

Parameters:

  • field: the name of the field to validate. It uses gjson for its json field extraction syntax.
  • errFmtFunc: a handler for formatting error messages.

func (Body) Chain

func (b Body) Chain() ValidationChain

Chain initializes a validation chain for the given body field. It creates a new ValidationChain object that will validate the specified field and format error messages using the provided ErrFmtFunc.

type Cookie struct {
	// contains filtered or unexported fields
}

Cookie is used to validate data from the `http.Request` cookies.

func NewCookie

func NewCookie(field string, errFmtFunc ErrFmtFunc) Cookie

NewCookie constructs a Cookie validator for the given field. Returns a Cookie object that can be used to create validation chains.

Parameters:

  • field: the name of the field to validate.
  • errFmtFunc: a handler for formatting error messages.

func (Cookie) Chain

func (c Cookie) Chain() ValidationChain

Chain initializes a validation chain for the given body field. It creates a new ValidationChain object that will validate the specified field and format error messages using the provided ErrFmtFunc.

type CustomSanitizerFunc

type CustomSanitizerFunc func(r *http.Request, initialValue, sanitizedValue string) string

CustomSanitizerFunc defines a function that computes and returns the new sanitized value.

Parameters:

  • req: The HTTP request context derived from `http.Request`.
  • initialValue: The original value derived from the specified field.
  • sanitizedValue: The current sanitized value after applying previous sanitizers.

type CustomValidatorFunc

type CustomValidatorFunc func(r *http.Request, initialValue, sanitizedValue string) bool

CustomValidatorFunc defines a function that evaluates whether the value is valid according to your custom logic.

Parameters:

  • r: The HTTP request context derived from `http.Request`.
  • initialValue: The original value derived from the specified field.
  • sanitizedValue: The current sanitized value after applying previous sanitizers.

type ErrFmtFunc added in v1.0.0

type ErrFmtFunc func(initialValue, sanitizedValue, validatorName string) string

ErrFmtFunc is a function type used to format validation error messages. It takes in the initial and sanitized values of a field, along with the name of the validator that triggered the error, and returns a formatted error message as a string.

Parameters:

  • initialValue: The original value of the field before sanitization.
  • sanitizedValue: The value of the field after applying sanitization or validation.
  • validatorName: The name of the validator that was applied and caused the error.

Returns:

  • A string representing the formatted error message based on the provided values and validator.
var DefaultErrFmtFunc ErrFmtFunc

DefaultErrFmtFunc is a package-level fallback error message formatter. When set, it is used for any validation chain that does not have its own errFmtFunc. If nil (the default), the system falls back to the validatorgo error message, then to DefaultErrMsg.

type Header struct {
	// contains filtered or unexported fields
}

Header is used to validate data from the `http.Request` headers.

func NewHeader

func NewHeader(field string, errFmtFunc ErrFmtFunc) Header

NewHeader constructs a Header validator for the given field. Returns a Header object that can be used to create validation chains.

Parameters:

  • field: the name of the field to validate.
  • errFmtFunc: a handler for formatting error messages.

func (Header) Chain

func (h Header) Chain() ValidationChain

Chain initializes a validation chain for the given body field. It creates a new ValidationChain object that will validate the specified field and format error messages using the provided ErrFmtFunc.

type IfModifierFunc

type IfModifierFunc func(r *http.Request, initialValue, sanitizedValue string) bool

IfModifierFunc defines a function that determines whether the validation chain should stop or continue. It returns `true` if the chain should stop, or `false` if it should continue.

Parameters:

  • req: the HTTP request context derived from `http.Request`.
  • initialValue: the original value derived from the specified field.
  • sanitizedValue: the current sanitized value after applying previous sanitizers.

type MatchedData

type MatchedData map[string]MatchedDataFieldValues

MatchedData is a map of request locations and fields. The keys in MatchedData represent the request locations where fields can be found. Possible locations include:

  • "body": Data from the request body.
  • "cookies": Data from request cookies.
  • "headers": Data from request headers.
  • "params": Data from URL parameters.
  • "queries": Data from URL query parameters.

func GetMatchedData

func GetMatchedData(ctx *gin.Context) (MatchedData, error)

GetMatchedData extracts and returns matched data from various locations in the request context. It retrieves fields and values from predefined request locations such as query parameters, body, URL parameters, and headers.

Parameters:

  • ctx: The Gin context, which provides access to the HTTP request and response.

Returns:

  • MatchedData: A map containing fields and their values organized by request location.
  • error: An error if there was an issue extracting data from the context; otherwise, nil.

func (MatchedData) Get added in v0.2.0

func (md MatchedData) Get(loc RequestLocation, field string) (string, bool)

Get retrieves a specific field's value from a given request location within MatchedData. Parameters:

  • loc: The request location to search in (e.g., "body", "cookies", "headers", "params", "queries").
  • field: The name of the field to retrieve.

Returns:

  • The value associated with the specified field at the given location (as a string).
  • A boolean indicating if the field exists (true if found, false if not).

func (MatchedData) Has added in v1.0.0

func (md MatchedData) Has(loc RequestLocation, field string) bool

Has reports whether a field exists at the given request location.

type MatchedDataFieldValues

type MatchedDataFieldValues map[string]string

MatchedDataFieldValues is a map of fields and their values for a request location.

type Param

type Param struct {
	// contains filtered or unexported fields
}

Param is used to validate data from the gins route parameters.

func NewParam

func NewParam(field string, errFmtFunc ErrFmtFunc) Param

NewParam constructs a Param validator for the given field. Returns a Param object that can be used to create validation chains.

Parameters:

  • field: the name of the field to validate.
  • errFmtFunc: a handler for formatting error messages.

func (Param) Chain

func (p Param) Chain() ValidationChain

Chain initializes a validation chain for the given body field. It creates a new ValidationChain object that will validate the specified field and format error messages using the provided ErrFmtFunc.

type Query

type Query struct {
	// contains filtered or unexported fields
}

Query is used to validate data from the `http.Request` queries.

func NewQuery

func NewQuery(field string, errFmtFunc ErrFmtFunc) Query

NewQuery constructs a Query validator for the given field. Returns a Query object that can be used to create validation chains.

Parameters:

  • field: the name of the field to validate.
  • errFmtFunc: a handler for formatting error messages.

func (Query) Chain

func (q Query) Chain() ValidationChain

Chain initializes a validation chain for the given body field. It creates a new ValidationChain object that will validate the specified field and format error messages using the provided ErrFmtFunc.

type RequestLocation

type RequestLocation int

RequestLocation defines different locations where data can be extracted from the request.

const (
	// BodyLocation represents the request body.
	BodyLocation RequestLocation = iota

	// CookieLocation represents cookies in the request.
	CookieLocation

	// HeaderLocation represents the headers in the request.
	HeaderLocation

	// ParamLocation represents path parameters in the request.
	ParamLocation

	// QueryLocation represents query parameters in the URL of the request.
	QueryLocation
)

Constants representing different locations in a request.

func (RequestLocation) String

func (l RequestLocation) String() string

String returns a string representation of the RequestLocation.

type Schema added in v1.0.0

type Schema map[string]SchemaField

Schema maps field names to their validation configuration.

type SchemaField added in v1.0.0

type SchemaField struct {
	// In specifies which request location the field comes from (body, cookies,
	// headers, params, or queries).
	In RequestLocation

	// ErrFmtFunc is an optional per-field error message formatter.
	// When nil, the package-level fallback rules apply.
	ErrFmtFunc ErrFmtFunc

	// Optional, when true, skips validation if the field is empty.
	Optional bool

	// Build receives a fresh [ValidationChain] and returns the configured
	// chain with validators, sanitizers, and modifiers attached.
	// Use .Bail() within the Build function to stop on the first failure.
	// If nil the chain runs with no validators (always passes).
	Build func(ValidationChain) ValidationChain
}

SchemaField describes how a single field should be validated within a Schema.

type SkipModifierFunc

type SkipModifierFunc func(r *http.Request, initialValue, sanitizedValue string) bool

SkipModifierFunc defines a function that determines wwhether the next validator, modifier or sanitizer in validation chain should be skipped. It returns `true` if the next chain should skipped, or `false` if it should continue.

Parameters:

  • req: the HTTP request context derived from `http.Request`.
  • initialValue: the original value derived from the specified field.
  • sanitizedValue: the current sanitized value after applying previous sanitizers.

type ValidationChain

type ValidationChain struct {
	// contains filtered or unexported fields
}

func NewBodyChain added in v1.0.0

func NewBodyChain(field string, errFmtFunc ErrFmtFunc) ValidationChain

NewBodyChain is a shorthand for NewBody(field, errFmtFunc).Chain().

func NewCookieChain added in v1.0.0

func NewCookieChain(field string, errFmtFunc ErrFmtFunc) ValidationChain

NewCookieChain is a shorthand for NewCookie(field, errFmtFunc).Chain().

func NewHeaderChain added in v1.0.0

func NewHeaderChain(field string, errFmtFunc ErrFmtFunc) ValidationChain

NewHeaderChain is a shorthand for NewHeader(field, errFmtFunc).Chain().

func NewParamChain added in v1.0.0

func NewParamChain(field string, errFmtFunc ErrFmtFunc) ValidationChain

NewParamChain is a shorthand for NewParam(field, errFmtFunc).Chain().

func NewQueryChain added in v1.0.0

func NewQueryChain(field string, errFmtFunc ErrFmtFunc) ValidationChain

NewQueryChain is a shorthand for NewQuery(field, errFmtFunc).Chain().

func (ValidationChain) AbaRouting

func (v ValidationChain) AbaRouting() ValidationChain

AbaRouting is a validator that checks if the string is an ABA routing number for US bank account / cheque.

This function uses the IsAbaRouting from validatorgo package to perform the validation logic.

func (ValidationChain) After

func (v ValidationChain) After(opts *vgo.IsAfterOpts) ValidationChain

After is a validator that checks if the string is a date that is after the specified date.

This function uses the IsAfter from validatorgo package to perform the validation logic.

func (ValidationChain) Alpha

func (v ValidationChain) Alpha(opts *vgo.IsAlphaOpts) ValidationChain

Alpha is a validator that checks if the string contains only letters (a-zA-Z).

This function uses the IsAlpha from validatorgo package to perform the validation logic.

func (ValidationChain) Alphanumeric

func (v ValidationChain) Alphanumeric(opts *vgo.IsAlphanumericOpts) ValidationChain

Alphanumeric is a validator that checks if the string contains only letters and numbers (a-zA-Z0-9).

This function uses the IsAlphanumeric from validatorgo package to perform the validation logic.

func (ValidationChain) Array added in v0.3.1

func (v ValidationChain) Array(opts *vgo.IsArrayOpts) ValidationChain

Base32 is a validator to check that a value is an array.

This function uses the IsArray from validatorgo package to perform the validation logic.

func (ValidationChain) Ascii

func (v ValidationChain) Ascii() ValidationChain

Ascii is a validator that checks if the string contains ASCII chars only.

This function uses the IsAscii from validatorgo package to perform the validation logic.

func (ValidationChain) BTCAddress

func (v ValidationChain) BTCAddress() ValidationChain

BTCAddress is a validator that checks if the string is a valid BTC address.

This function uses the IsBTCAddress from validatorgo package to perform the validation logic.

func (ValidationChain) Bail

func (m ValidationChain) Bail() ValidationChain

Bail is a modifier that stops running the validation chain if any of the previous validators failed.

This is useful to prevent a custom validator that touches a database or external API from running when you know it will fail.

.Bail() can be used multiple times in the same validation chain if desired.

func (ValidationChain) Base32

func (v ValidationChain) Base32(opts *vgo.IsBase32Opts) ValidationChain

Base32 is a validator that checks if the string is base32 encoded.

This function uses the IsBase32 from validatorgo package to perform the validation logic.

func (ValidationChain) Base58

func (v ValidationChain) Base58() ValidationChain

Base58 is a validator that checks if the string is base32 encoded.

This function uses the IsBase58 from validatorgo package to perform the validation logic.

func (ValidationChain) Base64

func (v ValidationChain) Base64(opts *vgo.IsBase64Opts) ValidationChain

Base64 is a validator that checks if the string is base64 encoded.

This function uses the IsBase64 from validatorgo package to perform the validation logic.

func (ValidationChain) Before

func (v ValidationChain) Before(opts *vgo.IsBeforeOpts) ValidationChain

Before is a validator that checks if the string is a date that is before the specified date.

This function uses the IsBefore from validatorgo package to perform the validation logic.

func (ValidationChain) Bic

func (v ValidationChain) Bic() ValidationChain

Bic is a validator that checks if the string is a BIC (Bank Identification Code) or SWIFT code.

This function uses the IsBic from validatorgo package to perform the validation logic.

func (ValidationChain) Blacklist

func (s ValidationChain) Blacklist(blacklistedChars string) ValidationChain

Blacklist is a sanitizer that remove characters that appear in the blacklist.

This function uses the validatorgo package to perform the sanitization logic.

Its parameters are according to Blacklist.

func (ValidationChain) Boolean

func (v ValidationChain) Boolean(opts *vgo.IsBooleanOpts) ValidationChain

Boolean validator that checks if the string is a boolean.

This function uses the IsBoolean from validatorgo package to perform the validation logic.

func (ValidationChain) ByteLength

func (v ValidationChain) ByteLength(opts *vgo.IsByteLengthOpts) ValidationChain

ByteLength is a validator that checks if the string's length (in UTF-8 bytes) falls in a range.

This function uses the IsByteLength from validatorgo package to perform the validation logic.

func (ValidationChain) Contains

func (v ValidationChain) Contains(seed string, opts *vgo.ContainsOpt) ValidationChain

Contains is a validator that checks if the string contains the seed.

This function uses the [Contains] from validatorgo package to perform the validation logic.

func (ValidationChain) CreditCard

func (v ValidationChain) CreditCard(opts *vgo.IsCreditCardOpts) ValidationChain

CreditCard is a validator that checks if the string is a credit card number.

This function uses the IsCreditCard from validatorgo package to perform the validation logic.

func (ValidationChain) Currency

func (v ValidationChain) Currency(opts *vgo.IsCurrencyOpts) ValidationChain

Currency is a validator that checks if the string is a valid currency amount.

This function uses the IsCurrency from validatorgo package to perform the validation logic.

func (ValidationChain) CustomSanitizer

func (s ValidationChain) CustomSanitizer(csf CustomSanitizerFunc) ValidationChain

CustomSanitizer applies a custom sanitizer function to compute the new sanitized value.

Parameters:

func (ValidationChain) CustomValidator

func (v ValidationChain) CustomValidator(cvf CustomValidatorFunc) ValidationChain

CustomValidator applies a custom validator function.

Parameters:

func (ValidationChain) DataURI

func (v ValidationChain) DataURI() ValidationChain

DataURI is a validator that checks if the string is a data uri format.

This function uses the IsDataURI from validatorgo package to perform the validation logic.

func (ValidationChain) Date

func (v ValidationChain) Date(opts *vgo.IsDateOpts) ValidationChain

Date is a validator that checks if the string is a valid date. e.g. 2002-07-15.

This function uses the IsDate from validatorgo package to perform the validation logic.

func (ValidationChain) Decimal

func (v ValidationChain) Decimal(opts *vgo.IsDecimalOpts) ValidationChain

Decimal is a validator that checks if the string represents a decimal number, such as 0.1, .3, 1.1, 1.00003, 4.0, etc.

This function uses the IsDecimal from validatorgo package to perform the validation logic.

func (ValidationChain) DivisibleBy

func (v ValidationChain) DivisibleBy(num int) ValidationChain

DivisibleBy is a validator thats checks if the string is a number(integer not a floating point) that is divisible by another(integer not a floating point).

This function uses the IsDivisibleBy from validatorgo package to perform the validation logic.

func (ValidationChain) EAN

func (v ValidationChain) EAN() ValidationChain

EAN is validator that checks if the string is a valid EAN (European Article Number).

This function uses the IsEAN from validatorgo package to perform the validation logic.

func (ValidationChain) Email

func (v ValidationChain) Email(opts *vgo.IsEmailOpts) ValidationChain

Email is a validator that checks if the string is an email.

This function uses the IsEmail from validatorgo package to perform the validation logic.

func (ValidationChain) Empty

func (v ValidationChain) Empty(opts *vgo.IsEmptyOpts) ValidationChain

Empty is a validator that checks if the string is an email.

This function uses the IsEmpty from validatorgo package to perform the validation logic.

func (ValidationChain) Equals

func (v ValidationChain) Equals(comparison string) ValidationChain

Equals is a validator that checks if the string contains the seed.

This function uses the [Equals] from validatorgo package to perform the validation logic.

func (ValidationChain) Escape

func (s ValidationChain) Escape() ValidationChain

Escape is a sanitizer that replaces <, >, &, ' and ". with HTML entities.

This function uses the validatorgo package to perform the sanitization logic.

Its parameters are according to Escape.

func (ValidationChain) EthereumAddress

func (v ValidationChain) EthereumAddress() ValidationChain

EthereumAddress is a validator checks if the string is an Ethereum address.

This function uses the IsEthereumAddress from validatorgo package to perform the validation logic.

func (ValidationChain) FQDN

func (v ValidationChain) FQDN(opts *vgo.IsFQDNOpts) ValidationChain

FQDN is a validator that checks if the string is a fully qualified domain name (e.g. domain.com).

This function uses the IsFQDN from validatorgo package to perform the validation logic.

func (ValidationChain) Float

func (v ValidationChain) Float(opts *vgo.IsFloatOpts) ValidationChain

Float is a validator that checks if the string is a float.

This function uses the IsFloat from validatorgo package to perform the validation logic.

func (ValidationChain) FreightContainerID

func (v ValidationChain) FreightContainerID() ValidationChain

FreightContainerID is a validator that checks alias for IsISO6346, check if the string is a valid ISO 6346 shipping container identification.

This function uses the IsFreightContainerID from validatorgo package to perform the validation logic.

func (ValidationChain) FullWidth

func (v ValidationChain) FullWidth() ValidationChain

FullWidth validator that checks if the string contains any full-width chars.

This function uses the IsFullWidth from validatorgo package to perform the validation logic.

func (ValidationChain) HSL

func (v ValidationChain) HSL() ValidationChain

HSL is a validator that checks if the string is an HSL (hue, saturation, lightness, optional alpha) color based on CSS Colors Level 4 specification.

This function uses the IsHSL from validatorgo package to perform the validation logic.

func (ValidationChain) HalfWidth

func (v ValidationChain) HalfWidth() ValidationChain

HalfWidth is a validator that checks if the string contains any half-width chars.

This function uses the IsHalfWidth from validatorgo package to perform the validation logic.

func (ValidationChain) Hash

func (v ValidationChain) Hash(algorithm string) ValidationChain

Hash is a validator that checks if the string is a hash of type algorithm.

This function uses the IsHash from validatorgo package to perform the validation logic.

func (ValidationChain) HexColor

func (v ValidationChain) HexColor() ValidationChain

HexColor is a validator that checks if the string is a hexadecimal color.

This function uses the IsHexColor from validatorgo package to perform the validation logic.

func (ValidationChain) Hexadecimal

func (v ValidationChain) Hexadecimal() ValidationChain

Hexadecimal is a validator that checks if the string is a hexadecimal number.

This function uses the IsHexadecimal from validatorgo package to perform the validation logic.

func (ValidationChain) IBAN

func (v ValidationChain) IBAN(countryCode string) ValidationChain

IBAN is a validator that checks if the string is an IBAN (International Bank Account Number).

This function uses the IsIBAN from validatorgo package to perform the validation logic.

func (ValidationChain) IMEI

func (v ValidationChain) IMEI(opts *vgo.IsIMEIOpts) ValidationChain

IMEI is a validator that checks if the string is a valid IMEI number.

This function uses the IsIMEI from validatorgo package to perform the validation logic.

func (ValidationChain) IP

func (v ValidationChain) IP(version string) ValidationChain

IP is a validator that checks if the string is an IP (version 4 or 6).

This function uses the IsIP from validatorgo package to perform the validation logic.

func (ValidationChain) IPRange

func (v ValidationChain) IPRange(version string) ValidationChain

IPRange is a validator that checks if the string is an IPRange (version 4 or 6).

This function uses the IsIPRange from validatorgo package to perform the validation logic.

func (ValidationChain) ISIN

func (v ValidationChain) ISIN() ValidationChain

ISIN is a validator that checks if the string is an ISIN (stock/security identifier).

This function uses the IsISIN from validatorgo package to perform the validation logic.

func (ValidationChain) ISO4217

func (v ValidationChain) ISO4217() ValidationChain

ISO4217 is a validator that checks if the string is a valid ISO 4217 officially assigned.

This function uses the IsISO4217 from validatorgo package to perform the validation logic.

func (ValidationChain) ISO6346

func (v ValidationChain) ISO6346() ValidationChain

ISO6346 is a validator that checks if the string is a valid ISO 6346 shipping container identification.

This function uses the IsISO6346 from validatorgo package to perform the validation logic.

func (ValidationChain) ISO6391

func (v ValidationChain) ISO6391() ValidationChain

ISO6391 is a validator that checks if the string is a valid ISO 639-1 language code.

This function uses the IsISO6391 from validatorgo package to perform the validation logic.

func (ValidationChain) ISO8601

func (v ValidationChain) ISO8601(opts *vgo.IsISO8601Opts) ValidationChain

ISO8601 is a validator that checks if the string is a valid ISO 8601 date.

This function uses the IsISO8601 from validatorgo package to perform the validation logic.

func (ValidationChain) ISO31661Alpha2

func (v ValidationChain) ISO31661Alpha2() ValidationChain

ISO31661Alpha2 is a validator that checks if the string is a valid ISO 3166-1 alpha-2 officially assigned country code.

This function uses the IsISO31661Alpha2 from validatorgo package to perform the validation logic.

func (ValidationChain) ISO31661Alpha3

func (v ValidationChain) ISO31661Alpha3() ValidationChain

ISO31661Alpha3 is a validator that checks if the string is a valid ISO 3166-1 alpha-2 officially assigned country code.

This function uses the IsISO31661Alpha3 from validatorgo package to perform the validation logic.

func (ValidationChain) ISO31661Numeric

func (v ValidationChain) ISO31661Numeric() ValidationChain

ISO31661Numeric is a validator that checks check if the string is a valid ISO 3166-1 numeric officially assigned country code.

This function uses the IsISO31661Numeric from validatorgo package to perform the validation logic.

func (ValidationChain) ISRC

func (v ValidationChain) ISRC(allowHyphens bool) ValidationChain

ISRC is a validator that checks if the string is an ISRC.

This function uses the IsISRC from validatorgo package to perform the validation logic.

func (ValidationChain) ISSN

func (v ValidationChain) ISSN(opts *vgo.IsISSNOpts) ValidationChain

ISSN is a validator that checks if the string is an ISSN.

This function uses the IsISSN from validatorgo package to perform the validation logic.

func (ValidationChain) IdentityCard

func (v ValidationChain) IdentityCard(locale string) ValidationChain

IdentityCard is a validator that checks if the string is a valid identity card code.

This function uses the IsIdentityCard from validatorgo package to perform the validation logic.

func (ValidationChain) If

func (m ValidationChain) If(imf IfModifierFunc) ValidationChain

If adds a conditional check to decide whether the validation chain should continue for a field.

The condition is evaluated by the provided IfModifierFunc and the result determines if the validation chain should bail out (`true`) or proceed (`false`).

Parameters:

func (ValidationChain) In

func (v ValidationChain) In(values []string) ValidationChain

In is a validator that checks if the string is in a slice of allowed values.

This function uses the IsIn from validatorgo package to perform the validation logic.

func (ValidationChain) Int

func (v ValidationChain) Int(opts *vgo.IsIntOpts) ValidationChain

Int is a validator that checks if the string is an integer.

This function uses the IsInt from validatorgo package to perform the validation logic.

func (ValidationChain) JSON

func (v ValidationChain) JSON() ValidationChain

JSON is a validator that checks if the string is an JSON.

This function uses the IsJSON from validatorgo package to perform the validation logic.

func (ValidationChain) LTrim

func (s ValidationChain) LTrim(chars string) ValidationChain

LTrim is a sanitizer that trims characters (whitespace by default) from the left-side of the input.

This function uses the validatorgo package to perform the sanitization logic.

Its parameters are according to LTrim.

func (ValidationChain) LatLong

func (v ValidationChain) LatLong(opts *vgo.IsLatLongOpts) ValidationChain

LatLong is a validator that checks if the string is a valid latitude-longitude coordinate.

This function uses the IsLatLong from validatorgo package to perform the validation logic.

func (ValidationChain) Length added in v0.3.1

func (v ValidationChain) Length(opts *vgo.IsLengthOpts) ValidationChain

length is a validator that checks if the string's length falls in a range.

This function uses the IsLength from validatorgo package to perform the validation logic.

func (ValidationChain) LicensePlate

func (v ValidationChain) LicensePlate(locale string) ValidationChain

LicensePlate is a validator that checks if the string matches the format of a country's license plate.

This function uses the IsLicensePlate from validatorgo package to perform the validation logic.

func (ValidationChain) Locale

func (v ValidationChain) Locale() ValidationChain

Locale is a validator that checks if the string is a locale.

This function uses the IsLocale from validatorgo package to perform the validation logic.

func (ValidationChain) LowerCase

func (v ValidationChain) LowerCase() ValidationChain

LowerCase is a validator that checks if the string is lowercase.

This function uses the IsLowerCase from validatorgo package to perform the validation logic.

func (ValidationChain) LuhnNumber

func (v ValidationChain) LuhnNumber() ValidationChain

LuhnNumber is a validator that checks if the string passes the Luhn algorithm check.

This function uses the IsLuhnNumber from validatorgo package to perform the validation logic.

func (ValidationChain) MD5

func (v ValidationChain) MD5() ValidationChain

MD5 is a validator that checks if the string is a MD5 hash.

This function uses the IsMD5 from validatorgo package to perform the validation logic.

func (ValidationChain) MacAddress

func (v ValidationChain) MacAddress(opts *vgo.IsMacAddressOpts) ValidationChain

MacAddress is a validator that checks if the string is a MAC address.

This function uses the IsMacAddress from validatorgo package to perform the validation logic.

func (ValidationChain) MagnetURI

func (v ValidationChain) MagnetURI() ValidationChain

MagnetURI is a validator that checks if the string is a Magnet URI format.

This function uses the IsMagnetURI from validatorgo package to perform the validation logic.

func (ValidationChain) MailtoURI

func (v ValidationChain) MailtoURI(opts *vgo.IsMailToURIOpts) ValidationChain

MailtoURI is a validator that checks if the string is a Mailto URI format.

This function uses the IsMailtoURI from validatorgo package to perform the validation logic.

func (ValidationChain) Matches

func (v ValidationChain) Matches(re *regexp.Regexp) ValidationChain

Matches is a validator that checks if the string matches the regex.

This function uses the IsMatches from validatorgo package to perform the validation logic.

func (ValidationChain) MimeType

func (v ValidationChain) MimeType() ValidationChain

MimeType is a validator that checks if the string matches to a valid MIME type format.

This function uses the IsMimeType from validatorgo package to perform the validation logic.

func (ValidationChain) MobilePhone

func (v ValidationChain) MobilePhone(locales []string, opts *vgo.IsMobilePhoneOpts) ValidationChain

MobilePhone is a validator that checks if the string is a mobile phone number.

This function uses the IsMobilePhone from validatorgo package to perform the validation logic.

func (ValidationChain) MongoID

func (v ValidationChain) MongoID() ValidationChain

MongoID is a validator that checks if the string is a valid hex-encoded representation of a MongoDB ObjectId.

This function uses the IsMongoID from validatorgo package to perform the validation logic.

func (ValidationChain) Multibyte

func (v ValidationChain) Multibyte() ValidationChain

Multibyte is a validator that checks if the string contains one or more multibyte chars.

This function uses the IsMultibyte from validatorgo package to perform the validation logic.

func (ValidationChain) NormalizeEmail

func (s ValidationChain) NormalizeEmail(opts *san.NormalizeEmailOpts) ValidationChain

NormalizeEmail is a sanitizer that canonicalizes an email address. (This doesn't validate that the input is an email, if you want to validate the email use IsEmail beforehand).

This function uses the validatorgo package to perform the sanitization logic.

Its parameters are according to NormalizeEmail.

func (ValidationChain) Not

func (m ValidationChain) Not() ValidationChain

Not negates the result of the next validator in the chain.

func (ValidationChain) Numeric

func (v ValidationChain) Numeric(opts *vgo.IsNumericOpts) ValidationChain

Numeric is a validator that checks if a string is a number.

This function uses the IsNumeric from validatorgo package to perform the validation logic.

func (ValidationChain) Object added in v0.3.1

func (v ValidationChain) Object(opts *vgo.IsObjectOpts) ValidationChain

Octal is a validator to check that a value is a json object.

This function uses the IsObject from validatorgo package to perform the validation logic.

func (ValidationChain) Octal

func (v ValidationChain) Octal() ValidationChain

Octal is a validator that checks if the string is a valid octal number.

This function uses the IsOctal from validatorgo package to perform the validation logic.

func (ValidationChain) Optional

func (m ValidationChain) Optional() ValidationChain

Optional ignores validation if the value is not present/empty, instead of failing it.

func (ValidationChain) PassportNumber

func (v ValidationChain) PassportNumber(countryCode string) ValidationChain

PassportNumber is a validator that checks if the string is a valid passport number.

This function uses the IsPassportNumber from validatorgo package to perform the validation logic.

func (ValidationChain) Port

func (v ValidationChain) Port() ValidationChain

Port is a validator that checks if the string is a valid port number.

This function uses the IsPort from validatorgo package to perform the validation logic.

func (ValidationChain) PostalCode

func (v ValidationChain) PostalCode(locale string) ValidationChain

PostalCode is a validator that checks if the string is a postal code.

This function uses the IsPostalCode from validatorgo package to perform the validation logic.

func (ValidationChain) RFC3339

func (v ValidationChain) RFC3339() ValidationChain

RFC3339 is a validator that checks if the string is a valid RFC 3339 date.

This function uses the IsRFC3339 from validatorgo package to perform the validation logic.

func (ValidationChain) RTrim

func (s ValidationChain) RTrim(chars string) ValidationChain

RTrim is a sanitizer that trims characters (whitespace by default) from the right-side of the input.

This function uses the validatorgo package to perform the sanitization logic.

Its parameters are according to RTrim.

func (ValidationChain) RgbColor

func (v ValidationChain) RgbColor(opts *vgo.IsRgbOpts) ValidationChain

RgbColor is a validator that checks if the string is a rgb or rgba color.

This function uses the IsRgbColor from validatorgo package to perform the validation logic.

func (ValidationChain) SemVer

func (v ValidationChain) SemVer() ValidationChain

SemVer is a validator that checks if the string is a Semantic Versioning Specification (SemVer).

This function uses the IsSemVer from validatorgo package to perform the validation logic.

func (ValidationChain) Skip

func (m ValidationChain) Skip(smf SkipModifierFunc) ValidationChain

Skip adds a conditional check to decide whether the next validator, modifier or sanitizer in validation chain should be skipped.

The condition is evaluated by the provided SkipModifierFunc and the result determines if the next link in validation chain should be skipped out (`true`) or proceed (`false`).

Parameters:

func (ValidationChain) Slug

func (v ValidationChain) Slug() ValidationChain

Slug is a validator that checks if the string is of type slug.

This function uses the IsSlug from validatorgo package to perform the validation logic.

func (ValidationChain) StripLow

func (s ValidationChain) StripLow(keepNewLines bool) ValidationChain

StripLow is a sanitizer that removes characters with a numerical value < 32 and 127, mostly control characters.

This function uses the validatorgo package to perform the sanitization logic.

Its parameters are according to StripLow.

func (ValidationChain) StrongPassword

func (v ValidationChain) StrongPassword(opts *vgo.IsStrongPasswordOpts) ValidationChain

StrongPassword is a validator that checks if the string is of type strongPassword.

This function uses the IsStrongPassword from validatorgo package to perform the validation logic.

func (ValidationChain) SurrogatePair

func (v ValidationChain) SurrogatePair() ValidationChain

SurrogatePair is a validator that checks if the string contains any surrogate pairs chars.

This function uses the IsSurrogatePair from validatorgo package to perform the validation logic.

func (ValidationChain) TaxID

func (v ValidationChain) TaxID(locale string) ValidationChain

TaxID is a validator that checks if the string is a valid Tax Identification Number.

This function uses the IsTaxID from validatorgo package to perform the validation logic.

func (ValidationChain) Time

func (v ValidationChain) Time(opts *vgo.IsTimeOpts) ValidationChain

Time is a validator that checks if the string is a valid time e.g. 23:01:59

This function uses the IsTime from validatorgo package to perform the validation logic.

func (ValidationChain) ToBoolean

func (s ValidationChain) ToBoolean(strict bool) ValidationChain

ToBoolean is a A sanitizer that converts the input string to a boolean as s string "true" or "false"

This function uses the validatorgo package to perform the sanitization logic.

Its parameters are according to ToBoolean.

func (ValidationChain) ToDate

func (s ValidationChain) ToDate() ValidationChain

ToDate is a sanitizer that converts the value too a textual representation.

This function uses the validatorgo package to perform the sanitization logic.

Its parameters are according to ToDate.

func (ValidationChain) ToFloat

func (s ValidationChain) ToFloat() ValidationChain

ToFloat is a sanitizer that converts the input string to a float64.

This function uses the validatorgo package to perform the sanitization logic.

Its parameters are according to ToFloat.

func (ValidationChain) ToInt

func (s ValidationChain) ToInt() ValidationChain

ToInt is a sanitizer that converts the input string to an int and also returns an error if the input is not a int. (Beware of octals)

This function uses the validatorgo package to perform the sanitization logic.

Its parameters are according to ToInt.

func (ValidationChain) Trim

func (s ValidationChain) Trim(chars string) ValidationChain

Trim is a sanitizer that trim characters (whitespace by default) from both sides of the input.

This function uses the validatorgo package to perform the sanitization logic.

Its parameters are according to Trim.

func (ValidationChain) ULID

func (v ValidationChain) ULID() ValidationChain

ULID is a validator that checks if the string is a ULID.

This function uses the IsULID from validatorgo package to perform the validation logic.

func (ValidationChain) URL

func (v ValidationChain) URL(opts *vgo.IsURLOpts) ValidationChain

URL is a validator that checks if the string is URL.

This function uses the IsURL from validatorgo package to perform the validation logic.

func (ValidationChain) UUID

func (v ValidationChain) UUID(version string) ValidationChain

UUID is a validator that checks if the string is an RFC9562 UUID.

This function uses the IsUUID from validatorgo package to perform the validation logic.

func (ValidationChain) Unescape

func (s ValidationChain) Unescape() ValidationChain

Unescape is a A sanitizer that replaces HTML encoded entities with <, >, &, ', ", `, \ and /.

This function uses the validatorgo package to perform the sanitization logic.

Its parameters are according to Unescape.

func (ValidationChain) UpperCase

func (v ValidationChain) UpperCase() ValidationChain

UpperCase is a validator that checks if the string is uppercase.

This function uses the IsUpperCase from validatorgo package to perform the validation logic.

func (ValidationChain) VAT

func (v ValidationChain) VAT(countryCode string) ValidationChain

VAT is a validator that checks if the string is a valid VAT.

This function uses the IsVAT from validatorgo package to perform the validation logic.

func (ValidationChain) Validate

func (v ValidationChain) Validate() gin.HandlerFunc

func (ValidationChain) VariableWidth

func (v ValidationChain) VariableWidth() ValidationChain

VariableWidth is a validator that checks if the string contains a mixture of full and half-width chars.

This function uses the IsVariableWidth from validatorgo package to perform the validation logic.

func (ValidationChain) Whitelist

func (s ValidationChain) Whitelist(whitelistedChars string) ValidationChain

Whitelist is a sanitizer that removes characters that do not appear in the whitelist.

This function uses the validatorgo package to perform the sanitization logic.

Its parameters are according to Whitelist.

func (ValidationChain) Whitelisted

func (v ValidationChain) Whitelisted(chars string) ValidationChain

Whitelisted is a validator that checks if the string consists only of characters that appear in the whitelist chars.

This function uses the IsWhitelisted from validatorgo package to perform the validation logic.

type ValidationChainError

type ValidationChainError struct {
	Location string `json:"location"`
	Message  string `json:"message"`
	Field    string `json:"field"`
	Value    string `json:"value"`
	Code     string `json:"code,omitempty"`
	// contains filtered or unexported fields
}

ValidationChainError represents an error that occurred during the validation chain for a request. It includes information about the location of the error, the message, the specific field involved, the invalid value.

Fields:

  • Location: The location in the request where the error occurred (e.g., "body", "cookies", "headers", "params", "queries").
  • Message: A message describing the validation error.
  • Field: The name of the field that failed validation.
  • Value: The invalid value that triggered the validation error.
  • Code: A machine-readable error code (e.g., "invalid_format") populated by validatorgo.
  • order: A monotonic counter used internally to preserve insertion order across chains.

func FirstError added in v1.0.0

func FirstError(ctx *gin.Context) *ValidationChainError

FirstError returns the first validation error, or nil if there are none.

func ValidationResult

func ValidationResult(ctx *gin.Context) ([]ValidationChainError, error)

ValidationResult extracts the validation errors from the Gin context. It retrieves any validation errors that have occurred during the request processing, and returns them as a slice of ValidationChainError structs along with any potential error.

Parameters:

  • ctx: The Gin context, which provides access to the HTTP request and response, including validation error data.

Returns:

  • A slice of ValidationChainError: Contains the details of each validation error encountered, including location, field, and message.
  • error: Returns an error if there is an issue extracting or processing the validation errors; otherwise, nil.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL