🔧 AI Nachrichten Major AI platforms go down in unprecedented simultaneous outage(03.09.2026 um 17:34 Uhr)
🔧 AI Nachrichten ChatGPT, Claude, and Grok Down? Users Report Widespread Outages(03.09.2026 um 19:14 Uhr)
🔧 AI Nachrichten OpenAI Launches GPT-6 Astra, Says We May Have Entered the AGI Era(03.09.2026 um 22:08 Uhr)
🔧 AI Nachrichten Claude Comes to CarPlay as Fifth Major AI Chatbot App(05.09.2026 um 05:31 Uhr)
🔧 AI Nachrichten OpenAI’s GPT-6 Astra Is AGI, Says NVIDIA CEO Jensen Huang(07.09.2026 um 06:31 Uhr)
🔧 AI Nachrichten Blame AI companies for Mac mini and Mac Studio shortage(31.08.2026 um 10:32 Uhr)
🔧 AI Nachrichten Major AI platforms go down in unprecedented simultaneous outage(03.09.2026 um 17:34 Uhr)
🔧 AI Nachrichten ChatGPT, Claude, and Grok Down? Users Report Widespread Outages(03.09.2026 um 19:14 Uhr)
🔧 AI Nachrichten OpenAI Launches GPT-6 Astra, Says We May Have Entered the AGI Era(03.09.2026 um 22:08 Uhr)
🔧 AI Nachrichten Claude Comes to CarPlay as Fifth Major AI Chatbot App(05.09.2026 um 05:31 Uhr)
🔧 AI Nachrichten OpenAI’s GPT-6 Astra Is AGI, Says NVIDIA CEO Jensen Huang(07.09.2026 um 06:31 Uhr)
🔧 AI Nachrichten Blame AI companies for Mac mini and Mac Studio shortage(31.08.2026 um 10:32 Uhr)

🔧 Programmierung 🕛 kürzlich 18 Min Lesezeit
0

Simplify Input Validation in Go with ginvalidator

↗ Quelle (dev.to)
🗣️ Stimme:
📑 Inhaltsübersicht




Overview



middlewares that wraps the extensive collection of validators and sanitizers offered by my other open source package 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 1.16+.

It's also verified to work with ):
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 to salute John!




💡 Tip:

You can use 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:




CODE
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()
}







📝 Note:


For brevity, gv is used as an alias for ginvalidator in the code examples.




Now, restart your server, and go to again, you’ll see the following JSON content, formatted for clarity:




CODE
{
"errors": [
{
"location": "queries",
"message": "Invalid value",
"field": "person",
"value": ""
}
]
}






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.




CODE
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",
func(initialValue, sanitizedValue, validatorName string) string {
return "Please enter your name."
},
).Chain().
Not().
Empty(nil).
Validate(),
func(ctx *gin.Context) {
result, err := gv.ValidationResult(ctx)
if err != nil {
ctx.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{
"message": "The server encountered an unexpected error.",
})
return
}

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

person := ctx.Query("person")
ctx.String(http.StatusOK, "Hello, %s!", person)
})

r.Run()
}






Now if you access 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 is one of the main concepts in ginvalidator, therefore it's useful to learn about it, so that you can use it effectively.



But don't worry: if you've read through the Getting Started guide, you have already used validation chains without even noticing!






What are validation chains?



Validation chains are created using the following functions, each targeting a specific location in the HTTP request:





  • NewBody: Validates data from the http.Request body. Its location is BodyLocation.


  • NewCookie: Validates data from the http.Request cookies. Its location is CookieLocation.


  • NewHeader: Validates data from the http.Request headers. Its location is HeaderLocation.


  • NewParam: Validates data from the Gin route parameters. Its location is ParamLocation.


  • NewQuery: Validates data from the http.Request query parameters. Its location is QueryLocation.



They have this name because they wrap the value of a field with validations (or sanitizations), and each of its methods returns itself.

This pattern is usually called














































  • Sanitizers transform the field value. They are useful to remove noise from the value and perhaps even to provide some basic line of defense against threats.



    Sanitizers persist the updated fields value back into the Gin Contexts, so that it's usable by other ginvalidator functions, your own route handler code, and even other middlewares.



    They are:













    Modifiers define how validation chains behave when they are run.



    They are:






    • . If any details are unclear, you may also want to refer to related functions within the validatorgo package for additional context, which I’ll be explaining below.







    Standard validators/sanitizers



    All of the functionality exposed by the validation chain actually comes from for extracting values. Please refer to the linked documentation for details.


  • Example:



  • CODE
      {
    "user": {
    "name": "John",
    "email": "[email protected]"
    }
    }




    With path user.name, the extracted value would be "John".





    • application/x-www-form-urlencoded: Typically used for HTML form submissions. Fields are submitted as key-value pairs in the body.


    • Example:



    CODE
      Content-Type: application/x-www-form-urlencoded




    Body:



    CODE
      name=John&[email protected]




    Field "name" would have the value "John", and "email" would have the value "[email protected]".





    • multipart/form-data: Commonly used for file uploads or when submitting form data with files.


    • Example:



    CODE
      Content-Type: multipart/form-data




    Body:



    CODE
      --boundary
    Content-Disposition: form-data; name="name"

    John
    --boundary
    Content-Disposition: form-data; name="file"; filename="resume.pdf"
    Content-Type: application/pdf

    [binary data]
    --boundary--




    Field "name" would have the value "John", and "file" would be the uploaded file.








  • Query fields correspond to URL search parameters, and their values are automatically url unescaped by Gin.


    Examples:




    • Field: "name", Value: "John"


    CODE
    /hello?name=John




    • Field: "full_name", Value: "John Doe"


    CODE
    /hello?full_name=John%20Doe




  • Param fields represent URL path parameters, and their values are automatically unescaped by ginvalidator.


    Example:




    • Field: "id", Value: "123"


    CODE
    /users/:id




  • Header fields are HTTP request headers, and their values are not unescaped. A log warning will appear if you provide a non-canonical header key.


    Example:




    • Field: "User-Agent", Value: "Mozilla/5.0"


    CODE
    Header: "User-Agent", Value: "Mozilla/5.0"




  • Cookies fields are HTTP cookies, and their values are automatically url unescaped by Gin.


    Example:




    • Field: "session_id", Value: "abc 123"


    CODE
    Cookie: "session_id=abc%20123"







  • Customizing express-validator



    If the server you're building is anything but a very simple one, you'll need validators, sanitizers and error messages beyond the ones built into ginvalidator sooner or later.





    Custom Validators and Sanitizers



    A classic need that ginvalidator can't fulfill for you, and that you might run into, is validating whether an e-mail address is in use or not when a user signing up.



    It's possible to do this in ginvalidator by implementing a custom validator.



    A CustomValidator is a method available on the validation chain, that receives a special function , and have to returns the new sanitized value.





    Implementing a custom validator



    A CustomValidator can be asynchronous by using goroutines and a sync.WaitGroup to handle concurrent operations. Within the validator, you can spin up goroutines for each asynchronous task, adding each task to the WaitGroup. Once all tasks complete, the validator should return a boolean.



    For example, in order to check that an e-mail is not in use:




    CODE
    func isUserPresent(email string) bool {
    return email == "[email protected]"
    }

    r.POST("/create-user",
    gv.
    NewBody("email", nil).
    Chain().
    CustomValidator(
    func(req *http.Request, initialValue, sanitizedValue string) bool {
    var exists bool
    var wg sync.WaitGroup
    wg.Add(1)

    go func() {
    defer wg.Done()
    exists = isUserPresent(sanitizedValue)
    }()

    wg.Wait()

    return !exists
    },
    ).
    Validate(),

    func(ctx *gin.Context) {
    // Handle the request
    },
    )






    Or maybe you could also verify that the password matches the repeat:




    CODE
    type createUser struct {
    Password string `json:"password"`
    PasswordConfirmation string `json:"passwordConfirmation"`
    }

    r.POST("/create-user",
    gv.NewBody("password", nil).
    Chain().
    Matches(regexp.MustCompile(`^[A-Za-z\d]{8,}$`)).
    Validate(),
    gv.NewBody("passwordConfirmation", nil).
    Chain().
    CustomValidator(func(req *http.Request, initialValue, sanitizedValue string) bool {
    data, err := io.ReadAll(req.Body)
    if err != nil {
    return false
    }

    // Refill the request body to allow further reads, if needed.
    req.Body = io.NopCloser(bytes.NewBuffer(data))

    var user createUser
    json.Unmarshal(data, &user)

    return sanitizedValue == user.PasswordConfirmation
    }).
    Validate(),
    func(ctx *gin.Context) {
    // Handle request
    },
    )







    ⚠️ Caution:

    If the request body will be accessed multiple times—whether in the same validation chain, in another validation chain for the same request context, or in subsequent handlers—ensure you reset the request body after each read. Failing to do so can lead to errors or missing data when the body is read again.







    Implementing a custom sanitizer



    CustomSanitizer don't have many rules. Whatever the value that they return, is the new value that the field will acquire.

    Custom sanitizers can also be asynchronous by using goroutines and a sync.WaitGroup to handle concurrent operations.




    CODE
    r.POST("/user/:id",
    gv.NewParam("id", nil).
    Chain().
    CustomSanitizer(
    func(req *http.Request, initialValue, sanitizedValue string) string {
    return strings.Repeat(sanitizedValue, 3) // some string manipulation
    },
    ).
    Validate(),

    func(ctx *gin.Context) {
    // Handle request
    },
    )









    Error Messages



    Whenever a field value is invalid, an error message is recorded for it.

    The default error message is "Invalid value", which is not descriptive at all of what the error is, so you might need to customize it. You can customize by




    CODE
    gv.NewBody("email",
    func(initialValue, sanitizedValue, validatorName string) string {
    switch validatorName {
    case gv.EmailValidatorName:
    return "Email is not valid."
    case gv.EmptyValidatorName:
    return "Email is empty."
    default:
    return gv.DefaultValChainErrMsg
    }
    },
    ).
    Chain().
    Not().Empty(nil).
    Email(nil).
    Validate()








    • initialValue is the original value extracted from the request (before any sanitization).


    • sanitizedValue is the value after it has been sanitized (if applicable).


    • validatorName is the name of the validator that failed, which helps identify the validation rule that did not pass.



    For a complete list of validator names, refer to the - Attah Gbubemi David (author)





    License



    This project is licensed under the file for details.

    Vollständiger Original-Bericht
    Ausführliche Details, Code-Beispiele & Hersteller-Stellungnahme auf dev.to.
    ↗ Original-Artikel auf dev.to lesen
    Wie bewertest du diesen Beitrag?
    1 Klick Feedback
    Teilen mit Netzwerk & Team:

    Community-Analysen & Experten-Meinungen 0

    Verfasse deine eigene Analyse, teile Workarounds oder diskutiere diesen Vorfall im Blog.
    Noch keine Community-Analyse verfasst. Markiere einen Textabschnitt oder klicke oben auf Eigene Analyse verfassen“!
    Community Pulse: Relevanz-Einschätzung
    1 Klick Experten-Votum
    🔴 Akute Relevanz 0%
    🟡 In Evaluierung 0%
    🟢 Keine Auswirkung 0%
    Spannende Innovation 0%
    Verwandte Story-Cluster & Quellen (Vektor-KI)
    Port 8095 Engine
    3 Quellen
    GPT-6 Astra Release Today? OpenAI’s Next Major AI Model Is Almost Here
    1 Quelle
    Apple accuses OpenAI of destroying evidence as trade-secrets fight intensifies
    1 Quelle
    Major AI platforms go down in unprecedented simultaneous outage
    Ähnliche Beiträge
    🔍 Verwandte News

    Auch interessante Nachrichten Simplify Input Validation in Go with ginvalidator

    Thematisch verwandte Begriffe: Simplify, Input, Validation, with · 6 Treffer

    Laden...

    Videos werden geladen ...

    Laden...

    Beiträge werden geladen ...

    Laden...

    Videos werden geladen ...

    Laden...

    Beiträge werden geladen ...

    Laden...

    Videos werden geladen ...

    Laden...

    Beiträge werden geladen ...

    Laden...

    Videos werden geladen ...

    Laden...

    Beiträge werden geladen ...

    Laden...

    Videos werden geladen ...