From 2e0de54d473bf4a9ed61ef93a19c2ab16e906852 Mon Sep 17 00:00:00 2001 From: rach-ba Date: Wed, 27 Sep 2023 14:27:18 +0200 Subject: [PATCH] [gapi] add pattern body validation --- examples/3-params/internal/body_with_validation.go | 4 +++- middleware/body_decoder.go | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/examples/3-params/internal/body_with_validation.go b/examples/3-params/internal/body_with_validation.go index f80db94..f08983f 100644 --- a/examples/3-params/internal/body_with_validation.go +++ b/examples/3-params/internal/body_with_validation.go @@ -30,7 +30,9 @@ type OrderBody struct { // The required tag validates that the value is not the data types default zero value // For numbers ensures value is not zero. For strings ensures value is not "". // For slices, maps, pointers, interfaces, channels and functions ensures the value is not nil. - ProductID string `json:"product_id" required:"true"` + // You can add validation using the pattern tag which is a regexp condition + // that the value of the field product_id must follow works also for float and integer + ProductID string `json:"product_id" required:"true" pattern:"^product_[\\d_]+"` // if you want to make a custom validation you can implement Validate() as the example bellow for quantity. Quantity int `json:"quantity"` } diff --git a/middleware/body_decoder.go b/middleware/body_decoder.go index d76eb70..ab05372 100644 --- a/middleware/body_decoder.go +++ b/middleware/body_decoder.go @@ -2,10 +2,12 @@ package middleware import ( "bytes" + "fmt" "io" "mime" "net/http" "reflect" + "regexp" "strings" "github.com/mwm-io/gapi/errors" @@ -124,6 +126,18 @@ func (m BodyDecoder) Wrap(h handler.Handler) handler.Handler { typeOfParameters := val.Type() typeOfFieldI := typeOfParameters.Field(i) + if pattern := typeOfFieldI.Tag.Get("pattern"); pattern != "" { + rex, errC := regexp.Compile(pattern) + if errC != nil { + return nil, errors.InternalServerError("pattern_must_be_regex", "pattern must contain a regular expression") + } + + fieldValue := val.Field(i).Interface() + if !rex.MatchString(fmt.Sprintf("%v", fieldValue)) { + return nil, errors.BadRequest("body_validation_failed", "field %s does not match the required pattern", typeOfFieldI.Name) + } + } + if typeOfFieldI.Tag.Get("required") != "true" { continue }