Simplify Gin Input Validation in Go with ginvalidator
Overview
ginvalidator is a set of Gin middlewares that wraps the extensive collection of validators and sanitizers offered by my other open source package validatorgo. It also uses the popular open-source package gjson for JSON field syntax, providing efficient querying and extraction of data from JSON objects.
It allows you to combine them in many ways so that you can validate and sanitize your Gin requests, and offers tools to determine if the request is valid or not, which data was matched according to your validators.
It is based on the popular js/express library express-validator
Support
This version of ginvalidator requires that your application is running on Go 1.16 .
It's also verified to work with Gin 1.x.x.
Rationale
Why not use?
- Handwritten Validators: You could write your own validation logic manually, but that gets repetitive and messy fast. Every time you need a new validation, you’re writing the same kind of code over and over. It’s easy to make mistakes, and it’s a pain to maintain.
- Gin's Built-in Model Binding and Validation: Gin has validation built in, but it’s not ideal for everyone. Struct tags are limiting and make your code harder to read, especially when you need complex rules. Plus, the validation gets tied too tightly to your models, which isn't great for flexibility.
- Other Libraries (like Galidator): There are other libraries out there, but they often feel too complex for what they do. They require more setup and work than you’d expect, especially when you just want a simple, straightforward solution for validation.
Installation
Make sure you have Go installed on your machine.
Step 1: Create a New Go Module
- Create an empty folder with a name of your choice.
- Open a terminal, navigate (cd) into that folder, and initialize a new Go module:
go mod init example.com/learning
Step 2: Install Required Packages
Use go get to install the necessary packages.
- Install Gin:
go get -u github.com/gin-gonic/gin
- Install ginvalidator:
go get -u github.com/bube054/ginvalidator
Getting Started
One of the best ways to learn something is by example! So let's roll the sleeves up and get some coding happening.
Setup
The first thing that one needs is a Gin server running. Let's implement one that says hi to someone; for this, create a main.go then add the following code:
package main import ( "net/http" "github.com/gin-gonic/gin" ) func main() { r := gin.Default() r.GET("/hello", func(ctx *gin.Context) { person := ctx.Query("person") ctx.String(http.StatusOK, "Hello, %s!", person) }) r.Run() // listen and serve on 0.0.0.0:8080 }
Now run this file by executing go run main.go on your terminal.
go mod init example.com/learning
The HTTP server should be running, and you can open http://localhost:8080/hello?person=John to salute John!
? Tip:
You can use Air with Go and Gin to implement live reload. These automatically restart the server whenever a file is changed, so you don't have to do this yourself!
Adding a validator
So the server is working, but there are problems with it. Most notably, you don't want to say hello to someone when the person's name is not set.
For example, going to http://localhost:8080/hello will print "Hello, ".
That's where ginvalidator comes in handy. It provides validators, sanitizers and modifiers that are used to validate your request.
Let's add a validator and a modifier that checks that the person query string cannot be empty, with the validator named Empty and modifier named Not:
go get -u github.com/gin-gonic/gin
? Note:
For brevity, gv is used as an alias for ginvalidator in the code examples.
Now, restart your server, and go to http://localhost:8080/hello again. Hmm, it still prints "Hello, !"... why?
Handling validation errors
ginvalidator validation chain does not report validation errors to users automatically.
The reason for this is simple: as you add more validators, or for more fields, how do you want to collect the errors? Do you want a list of all errors, only one per field, only one overall...?
So the next obvious step is to change the above code again, this time verifying the validation result with the ValidationResult function:
go get -u github.com/bube054/ginvalidator
Now, if you access http://localhost:8080/hello again, you’ll see the following JSON content, formatted for clarity:
package main import ( "net/http" "github.com/gin-gonic/gin" ) func main() { r := gin.Default() r.GET("/hello", func(ctx *gin.Context) { person := ctx.Query("person") ctx.String(http.StatusOK, "Hello, %s!", person) }) r.Run() // listen and serve on 0.0.0.0:8080 }
Now, what this is telling us is that
- there's been exactly one error in this request;
- this field is called person;
- it's located in the query string (location: "queries");
- the error message that was given was "Invalid value".
This is a better scenario, but it can still be improved. Let's continue.
Creating better error messages
All request location validators accept an optional second argument, which is a function used to format the error message. If nil is provided, a default, generic error message will be used, as shown in the example above.
go run main.go
Now if you access http://localhost:8080/hello again, what you'll see is the following JSON content, with the new error message:
package main import ( "net/http" gv "github.com/bube054/ginvalidator" "github.com/gin-gonic/gin" ) func main() { r := gin.Default() r.GET("/hello", gv.NewQuery("person", nil). Chain(). Not(). Empty(nil). Validate(), func(ctx *gin.Context) { person := ctx.Query("person") ctx.String(http.StatusOK, "Hello, %s!", person) }) r.Run() }
Accessing validated/sanitized data
You can use GetMatchedData, which automatically collects all data that ginvalidator has validated and/or sanitized. This data can then be accessed using the Get method of MatchedData:
go mod init example.com/learning
open http://localhost:8080/hello?person=John to salute John!
The available locations are BodyLocation, CookieLocation QueryLocation, ParamLocation and HeaderLocation.
Each of these locations includes a String method that returns the location where validated/sanitized data is being stored.
Sanitizing inputs
While the user can no longer send empty person names, it can still inject HTML into your page! This is known as the Cross-Site Scripting vulnerability (XSS).
Let's see how it works. Go to http://localhost:8080/hello?person=John, and you should see "Hello, John!".
While this example is fine, an attacker could change the person query string to a

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics











Go language performs well in building efficient and scalable systems. Its advantages include: 1. High performance: compiled into machine code, fast running speed; 2. Concurrent programming: simplify multitasking through goroutines and channels; 3. Simplicity: concise syntax, reducing learning and maintenance costs; 4. Cross-platform: supports cross-platform compilation, easy deployment.

Golang is better than Python in terms of performance and scalability. 1) Golang's compilation-type characteristics and efficient concurrency model make it perform well in high concurrency scenarios. 2) Python, as an interpreted language, executes slowly, but can optimize performance through tools such as Cython.

Golang is better than C in concurrency, while C is better than Golang in raw speed. 1) Golang achieves efficient concurrency through goroutine and channel, which is suitable for handling a large number of concurrent tasks. 2)C Through compiler optimization and standard library, it provides high performance close to hardware, suitable for applications that require extreme optimization.

Goimpactsdevelopmentpositivelythroughspeed,efficiency,andsimplicity.1)Speed:Gocompilesquicklyandrunsefficiently,idealforlargeprojects.2)Efficiency:Itscomprehensivestandardlibraryreducesexternaldependencies,enhancingdevelopmentefficiency.3)Simplicity:

Golang and Python each have their own advantages: Golang is suitable for high performance and concurrent programming, while Python is suitable for data science and web development. Golang is known for its concurrency model and efficient performance, while Python is known for its concise syntax and rich library ecosystem.

The performance differences between Golang and C are mainly reflected in memory management, compilation optimization and runtime efficiency. 1) Golang's garbage collection mechanism is convenient but may affect performance, 2) C's manual memory management and compiler optimization are more efficient in recursive computing.

Golang and C each have their own advantages in performance competitions: 1) Golang is suitable for high concurrency and rapid development, and 2) C provides higher performance and fine-grained control. The selection should be based on project requirements and team technology stack.

Golang is suitable for rapid development and concurrent scenarios, and C is suitable for scenarios where extreme performance and low-level control are required. 1) Golang improves performance through garbage collection and concurrency mechanisms, and is suitable for high-concurrency Web service development. 2) C achieves the ultimate performance through manual memory management and compiler optimization, and is suitable for embedded system development.
