mirror of
https://github.com/rjNemo/go-microservices-tuto
synced 2026-06-12 13:26:45 +00:00
👮🏽♀️ validate Product
This commit is contained in:
parent
7b50b02a04
commit
25ba22f650
5 changed files with 83 additions and 4 deletions
8
go.mod
8
go.mod
|
|
@ -2,4 +2,10 @@ module github.com/rjNemo/go-micro
|
||||||
|
|
||||||
go 1.14
|
go 1.14
|
||||||
|
|
||||||
require github.com/gorilla/mux v1.7.4
|
require (
|
||||||
|
github.com/go-playground/universal-translator v0.17.0 // indirect
|
||||||
|
github.com/go-playground/validator v9.31.0+incompatible
|
||||||
|
github.com/gorilla/mux v1.7.4
|
||||||
|
github.com/leodido/go-urn v1.2.0 // indirect
|
||||||
|
gopkg.in/go-playground/assert.v1 v1.2.1 // indirect
|
||||||
|
)
|
||||||
|
|
|
||||||
23
go.sum
23
go.sum
|
|
@ -1,2 +1,25 @@
|
||||||
|
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
|
||||||
|
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
||||||
|
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
|
||||||
|
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
||||||
|
github.com/go-playground/validator v9.31.0+incompatible h1:UA72EPEogEnq76ehGdEDp4Mit+3FDh548oRqwVgNsHA=
|
||||||
|
github.com/go-playground/validator v9.31.0+incompatible/go.mod h1:yrEkQXlcI+PugkyDjY2bRrL/UBU4f3rvrgkN3V8JEig=
|
||||||
github.com/gorilla/mux v1.7.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc=
|
github.com/gorilla/mux v1.7.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc=
|
||||||
github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||||
|
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
|
||||||
|
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||||
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM=
|
||||||
|
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
|
|
||||||
|
|
@ -79,10 +79,20 @@ func (p *Products) ProductValidationMiddleware(next http.Handler) http.Handler {
|
||||||
// deserialize JSON to product
|
// deserialize JSON to product
|
||||||
err := newProd.FromJSON(r.Body)
|
err := newProd.FromJSON(r.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
p.logger.Printf("Error deserializing %v", err)
|
||||||
errMsg := fmt.Sprintf("Unable to decode data: %s\n", err)
|
errMsg := fmt.Sprintf("Unable to decode data: %s\n", err)
|
||||||
http.Error(w, errMsg, http.StatusBadRequest)
|
http.Error(w, errMsg, http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// validate the product
|
||||||
|
err = newProd.Validate()
|
||||||
|
if err != nil {
|
||||||
|
p.logger.Printf("Error deserializing %v", err)
|
||||||
|
errMsg := fmt.Sprintf("Validation error: %s\n", err)
|
||||||
|
http.Error(w, errMsg, http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// add product to the context
|
// add product to the context
|
||||||
ctx := context.WithValue(r.Context(), KeyProduct{}, newProd)
|
ctx := context.WithValue(r.Context(), KeyProduct{}, newProd)
|
||||||
req := r.WithContext(ctx)
|
req := r.WithContext(ctx)
|
||||||
|
|
|
||||||
|
|
@ -3,15 +3,18 @@ package models
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io"
|
"io"
|
||||||
|
"regexp"
|
||||||
|
|
||||||
|
"github.com/go-playground/validator"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Product defines the structure of a product
|
// Product defines the structure of a product
|
||||||
type Product struct {
|
type Product struct {
|
||||||
ID int `json:"id"` //TODO: use uuid
|
ID int `json:"id"` //TODO: use uuid
|
||||||
Name string `json:"name"`
|
Name string `json:"name" validate:"required"`
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
Price float32 `json:"price"` // TODO: use int
|
Price float32 `json:"price" validate:"gt=0"` // TODO: use int
|
||||||
SKU string `json:"sku"`
|
SKU string `json:"sku" validate:"required,sku"`
|
||||||
CreatedOn string `json:"-"`
|
CreatedOn string `json:"-"`
|
||||||
UpdatedOn string `json:"-"`
|
UpdatedOn string `json:"-"`
|
||||||
DeletedOn string `json:"-"`
|
DeletedOn string `json:"-"`
|
||||||
|
|
@ -21,3 +24,22 @@ type Product struct {
|
||||||
func (p *Product) FromJSON(r io.Reader) error {
|
func (p *Product) FromJSON(r io.Reader) error {
|
||||||
return json.NewDecoder(r).Decode(p)
|
return json.NewDecoder(r).Decode(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validate checks object validity
|
||||||
|
func (p *Product) Validate() error {
|
||||||
|
validate := validator.New()
|
||||||
|
validate.RegisterValidation("sku", validateSKU)
|
||||||
|
return validate.Struct(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateSKU(fl validator.FieldLevel) bool {
|
||||||
|
// sku is of format abc-efgh-ijklm
|
||||||
|
re := regexp.MustCompile("[a-z]+-[a-z]+-[a-z]+")
|
||||||
|
matches := re.FindAllString(fl.Field().String(), -1)
|
||||||
|
|
||||||
|
if len(matches) != 1 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
|
||||||
18
products/models/product_test.go
Normal file
18
products/models/product_test.go
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestValidation(t *testing.T) {
|
||||||
|
p := &Product{
|
||||||
|
Name: "Frappe",
|
||||||
|
Price: 1.1,
|
||||||
|
SKU: "a-adfg-fdds",
|
||||||
|
}
|
||||||
|
|
||||||
|
err := p.Validate()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue