Skip to content

Commit

Permalink
feat(decoderx): explicit request query checking (#319)
Browse files Browse the repository at this point in the history
  • Loading branch information
aeneasr authored Apr 6, 2021
1 parent 44a3b19 commit eb295dc
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 1 deletion.
11 changes: 10 additions & 1 deletion decoderx/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ type (
maxCircularReferenceDepth uint8
handleParseErrors parseErrorStrategy
expectJSONFlattened bool
queryAndBody bool
}

// HTTPDecoderOption configures the HTTP decoder.
Expand Down Expand Up @@ -125,6 +126,14 @@ func HTTPDecoderAllowedMethods(method ...string) HTTPDecoderOption {
}
}

// HTTPDecoderUseQueryAndBody will check both the HTTP body and the HTTP query params when decoding.
// Only relevant for non-GET operations.
func HTTPDecoderUseQueryAndBody() HTTPDecoderOption {
return func(o *httpDecoderOptions) {
o.queryAndBody = true
}
}

// HTTPDecoderSetIgnoreParseErrorsStrategy sets a strategy for dealing with strconv.Parse* errors:
//
// - decoderx.ParseErrorIgnoreConversionErrors will ignore any parse errors caused by strconv.Parse* and use the
Expand Down Expand Up @@ -363,7 +372,7 @@ func (t *HTTP) decodeForm(r *http.Request, destination interface{}, o *httpDecod
}

values := r.PostForm
if r.Method == "GET" {
if r.Method == "GET" || o.queryAndBody {
values = r.Form
}

Expand Down
46 changes: 46 additions & 0 deletions decoderx/http_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,52 @@ func TestHTTPFormDecoder(t *testing.T) {
"newsletter": true,
"consent": true,
"ratio": 0.9
}`,
},
{
d: "should pass form request with payload in query and type assert data",
request: newRequest(t, "POST", "/?age=29", bytes.NewBufferString(url.Values{
"name.first": {"Aeneas"},
"name.last": {"Rekkas"},
"ratio": {"0.9"},
"consent": {"true"},
// newsletter represents a special case for checkbox input with true/false and raw HTML.
"newsletter": {
"false", // comes from <input type="hidden" name="newsletter" value="false">
"true", // comes from <input type="checkbox" name="newsletter" value="true" checked>
},
}.Encode()), httpContentTypeURLEncodedForm),
options: []HTTPDecoderOption{HTTPJSONSchemaCompiler("stub/person.json", nil)},
expected: `{
"name": {"first": "Aeneas", "last": "Rekkas"},
"newsletter": true,
"consent": true,
"ratio": 0.9
}`,
},
{
d: "should pass form request with payload in query and type assert data",
request: newRequest(t, "POST", "/?age=29", bytes.NewBufferString(url.Values{
"name.first": {"Aeneas"},
"name.last": {"Rekkas"},
"ratio": {"0.9"},
"consent": {"true"},
// newsletter represents a special case for checkbox input with true/false and raw HTML.
"newsletter": {
"false", // comes from <input type="hidden" name="newsletter" value="false">
"true", // comes from <input type="checkbox" name="newsletter" value="true" checked>
},
}.Encode()), httpContentTypeURLEncodedForm),
options: []HTTPDecoderOption{
HTTPDecoderUseQueryAndBody(),
HTTPJSONSchemaCompiler("stub/person.json", nil),
},
expected: `{
"name": {"first": "Aeneas", "last": "Rekkas"},
"age": 29,
"newsletter": true,
"consent": true,
"ratio": 0.9
}`,
},
{
Expand Down

0 comments on commit eb295dc

Please sign in to comment.