From 898d805ef607ddfc082c3cf50a486f0a64d0c75d Mon Sep 17 00:00:00 2001 From: "Gerasimos (Makis) Maropoulos" Date: Fri, 24 Jul 2020 20:49:43 +0300 Subject: [PATCH] export the Form and Query decoders in order to be customized by Iris users and ignore unknown url query parameters instead of giving an ErrPath relative to: https://github.com/kataras/iris/issues/1566 --- decoder.go | 15 ++++++++++----- go.mod | 2 +- schema.go | 15 ++++++--------- schema_test.go | 44 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 61 insertions(+), 15 deletions(-) create mode 100644 schema_test.go diff --git a/decoder.go b/decoder.go index 0deec30..18222a1 100644 --- a/decoder.go +++ b/decoder.go @@ -26,13 +26,15 @@ type Decoder struct { // AddAliasTag adds a tag used to locate custom field aliases. // Defaults are "schema", "form" and "url". -func (d *Decoder) AddAliasTag(tag ...string) { +func (d *Decoder) AddAliasTag(tag ...string) *Decoder { d.cache.tags = append(d.cache.tags, tag...) + return d } // SetAliasTag overrides the tags. -func (d *Decoder) SetAliasTag(tag ...string) { +func (d *Decoder) SetAliasTag(tag ...string) *Decoder { d.cache.tags = tag + return d } // ZeroEmpty controls the behaviour when the decoder encounters empty values @@ -43,8 +45,9 @@ func (d *Decoder) SetAliasTag(tag ...string) { // // The default value is false, that is empty values do not change // the value of the struct field. -func (d *Decoder) ZeroEmpty(z bool) { +func (d *Decoder) ZeroEmpty(z bool) *Decoder { d.zeroEmpty = z + return d } // IgnoreUnknownKeys controls the behaviour when the decoder encounters unknown @@ -55,13 +58,15 @@ func (d *Decoder) ZeroEmpty(z bool) { // will still be decoded in to the target struct. // // To preserve backwards compatibility, the default value is false. -func (d *Decoder) IgnoreUnknownKeys(i bool) { +func (d *Decoder) IgnoreUnknownKeys(i bool) *Decoder { d.ignoreUnknownKeys = i + return d } // RegisterConverter registers a converter function for a custom type. -func (d *Decoder) RegisterConverter(value interface{}, converterFunc Converter) { +func (d *Decoder) RegisterConverter(value interface{}, converterFunc Converter) *Decoder { d.cache.registerConverter(value, converterFunc) + return d } // Decode decodes a map[string][]string to a struct. diff --git a/go.mod b/go.mod index 5a05d0c..05b3a83 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,3 @@ module github.com/iris-contrib/schema -go 1.12 +go 1.14 diff --git a/schema.go b/schema.go index 50123e6..b76601b 100644 --- a/schema.go +++ b/schema.go @@ -2,15 +2,12 @@ package schema var ( defaultDecoder = NewDecoder() // form, url, schema. - formDecoder = NewDecoder() - queryDecoder = NewDecoder() + // Form Decoder. The default instance for DecodeForm function. + Form = NewDecoder().SetAliasTag("form") + // Query Decoder. The default instance for DecodeQuery function. + Query = NewDecoder().SetAliasTag("url").IgnoreUnknownKeys(true) // allow unknown url queries. ) -func init() { - formDecoder.SetAliasTag("form") - queryDecoder.SetAliasTag("url") -} - // Decode maps "values" to "ptr". // With one of the "form", "url" or "schema" tag fields that can override the field's name mapping to key. func Decode(values map[string][]string, ptr interface{}) error { @@ -20,13 +17,13 @@ func Decode(values map[string][]string, ptr interface{}) error { // DecodeForm maps "values" to "ptr". // With "form" tag for fields. func DecodeForm(values map[string][]string, ptr interface{}) error { - return formDecoder.Decode(ptr, values) + return Form.Decode(ptr, values) } // DecodeQuery maps "values" to "ptr". // With "url" tag for fields. func DecodeQuery(values map[string][]string, ptr interface{}) error { - return queryDecoder.Decode(ptr, values) + return Query.Decode(ptr, values) } // IsErrPath reports whether the incoming error is type of unknown field passed, diff --git a/schema_test.go b/schema_test.go new file mode 100644 index 0000000..67f99af --- /dev/null +++ b/schema_test.go @@ -0,0 +1,44 @@ +// package schema_test black box testing +package schema_test + +import ( + "testing" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/httptest" +) + +type testRequest struct { + Username string `form:"test_username" json:"test_username"` + Data []testData `form:"test_data" json:"test_data"` + Other int `form:"test_other" json:"test_other"` +} + +type testData struct { + Name string `form:"test_data_name" json:"test_data_name"` +} + +func TestSchemaSliceFieldTag(t *testing.T) { + app := iris.New() + app.Post("/", func(ctx iris.Context) { + var p testRequest + if err := ctx.ReadForm(&p); err != nil && iris.IsErrPath(err) { + t.Fatal(err) + } + + ctx.JSON(p) + }) + + payload := testRequest{ + Username: "test username", + Data: []testData{ + {Name: "test data name 1"}, + {Name: "test data name 2"}, + {Name: "test data name 3"}, + }, + Other: 42, + } + + e := httptest.New(t, app) + e.POST("/").WithForm(payload).Expect().Status(iris.StatusOK).JSON().Equal(payload) +}