Skip to content

Commit

Permalink
feat: added support for reading and validation queries into structs
Browse files Browse the repository at this point in the history
  • Loading branch information
noxecane committed Aug 20, 2020
1 parent 8896300 commit f1f2e3a
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 0 deletions.
56 changes: 56 additions & 0 deletions request_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package anansi

import (
"net/http"
"strconv"
"testing"

ozzo "github.com/go-ozzo/ozzo-validation/v4"
"syreclabs.com/go/faker"
)

type userQuery struct {
Name string `json:"name"`
Age int `json:"age"`
}

func (u *userQuery) Validate() error {
return ozzo.ValidateStruct(u,
ozzo.Field(&u.Name, ozzo.Required),
ozzo.Field(&u.Age, ozzo.Required),
)
}

func TestReadQuery(t *testing.T) {
fName := faker.Name().FirstName()
ageOne := faker.Number().Number(2)
ageTwo := faker.Number().Number(2)

req, err := http.NewRequest("GET", "https://google.com", nil)
if err != nil {
t.Fatal(err)
}
q := req.URL.Query()

q.Add("name", fName)
q.Add("age", ageOne)
q.Add("age", ageTwo)

req.URL.RawQuery = q.Encode()

uQ := new(userQuery)
ReadQuery(req, uQ)

if uQ.Name != fName {
t.Errorf("Expected name %s. got name %s", fName, uQ.Name)
}

uQAge, err := strconv.Atoi(ageOne)
if err != nil {
t.Fatal(err)
}

if uQ.Age != uQAge {
t.Errorf("Expected name %s. got name %s", fName, uQ.Name)
}
}
42 changes: 42 additions & 0 deletions requests.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (

"github.com/go-chi/chi"
ozzo "github.com/go-ozzo/ozzo-validation/v4"
"github.com/mitchellh/mapstructure"
)

// ReadBody extracts the bytes in a request body without destroying the contents of the body
Expand Down Expand Up @@ -84,6 +85,47 @@ func ReadJSON(r *http.Request, v interface{}) {
}
}

func ReadQuery(r *http.Request, v interface{}) {
raw := r.URL.Query()
qMap := make(map[string]string)

for k := range raw {
qMap[k] = raw.Get(k)
}

// convert claims data map to struct
config := &mapstructure.DecoderConfig{
Result: v,
TagName: "json",
WeaklyTypedInput: true,
}
decoder, err := mapstructure.NewDecoder(config)

if err != nil {
panic(APIError{
Code: http.StatusBadRequest,
Message: "We cannot parse your request body.",
Err: err,
})
}

if err := decoder.Decode(qMap); err != nil {
panic(APIError{
Code: http.StatusBadRequest,
Message: "We cannot parse your request body.",
Err: err,
})
}

if err := ozzo.Validate(v); err != nil {
panic(APIError{
Code: http.StatusBadRequest,
Message: "We could not validate your request.",
Meta: err,
})
}
}

// IDParam extracts a uint URL parameter from the given request
func IDParam(r *http.Request, name string) uint {
param := chi.URLParam(r, name)
Expand Down

0 comments on commit f1f2e3a

Please sign in to comment.