From 25aead0c4be648ece2475e3e8e9ba14180640f5b Mon Sep 17 00:00:00 2001 From: Steve Lessard Date: Thu, 15 Dec 2022 21:23:59 -0800 Subject: [PATCH] Fix issue #710 parse integer primitives as int32 or int64, rather than float64 --- openapi3filter/issue625_test.go | 2 +- openapi3filter/req_resp_decoder.go | 9 ++++++++- openapi3filter/req_resp_decoder_test.go | 25 ++++++++++++++++--------- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/openapi3filter/issue625_test.go b/openapi3filter/issue625_test.go index d9e5bae47..5642a7e00 100644 --- a/openapi3filter/issue625_test.go +++ b/openapi3filter/issue625_test.go @@ -72,7 +72,7 @@ paths: name: "failed allof object array", spec: allOfArraySpec, req: `/items?test=1.2,3.1`, - errStr: `parameter "test" in query has an error: Error at "/0": value "1.2" must be an integer`, + errStr: `parameter "test" in query has an error: path 0: value 1.2: an invalid integer: invalid syntax`, }, { name: "success oneof object array", diff --git a/openapi3filter/req_resp_decoder.go b/openapi3filter/req_resp_decoder.go index 52c65afaa..870651ce6 100644 --- a/openapi3filter/req_resp_decoder.go +++ b/openapi3filter/req_resp_decoder.go @@ -895,7 +895,14 @@ func parsePrimitive(raw string, schema *openapi3.SchemaRef) (interface{}, error) } switch schema.Value.Type { case "integer": - v, err := strconv.ParseFloat(raw, 64) + if schema.Value.Format == "int32" { + v, err := strconv.ParseInt(raw, 0, 32) + if err != nil { + return nil, &ParseError{Kind: KindInvalidFormat, Value: raw, Reason: "an invalid " + schema.Value.Type, Cause: err.(*strconv.NumError).Err} + } + return int32(v), nil + } + v, err := strconv.ParseInt(raw, 0, 64) if err != nil { return nil, &ParseError{Kind: KindInvalidFormat, Value: raw, Reason: "an invalid " + schema.Value.Type, Cause: err.(*strconv.NumError).Err} } diff --git a/openapi3filter/req_resp_decoder_test.go b/openapi3filter/req_resp_decoder_test.go index 8bd62b1c5..709cdc929 100644 --- a/openapi3filter/req_resp_decoder_test.go +++ b/openapi3filter/req_resp_decoder_test.go @@ -175,7 +175,7 @@ func TestDecodeParameter(t *testing.T) { name: "integer", param: &openapi3.Parameter{Name: "param", In: "path", Schema: integerSchema}, path: "/1", - want: float64(1), + want: int64(1), found: true, }, { @@ -456,7 +456,7 @@ func TestDecodeParameter(t *testing.T) { name: "integer", param: &openapi3.Parameter{Name: "param", In: "query", Schema: integerSchema}, query: "param=1", - want: float64(1), + want: int64(1), found: true, }, { @@ -522,7 +522,7 @@ func TestDecodeParameter(t *testing.T) { name: "anyofSchema integer", param: &openapi3.Parameter{Name: "param", In: "query", Schema: anyofSchema}, query: "param=1", - want: float64(1), + want: int64(1), found: true, }, { @@ -548,7 +548,7 @@ func TestDecodeParameter(t *testing.T) { name: "oneofSchema int", param: &openapi3.Parameter{Name: "param", In: "query", Schema: oneofSchema}, query: "param=1122", - want: float64(1122), + want: int64(1122), found: true, }, { @@ -724,7 +724,7 @@ func TestDecodeParameter(t *testing.T) { name: "integer", param: &openapi3.Parameter{Name: "X-Param", In: "header", Schema: integerSchema}, header: "X-Param:1", - want: float64(1), + want: int64(1), found: true, }, { @@ -835,6 +835,13 @@ func TestDecodeParameter(t *testing.T) { want: map[string]interface{}{"id": "foo", "name": "bar"}, found: true, }, + { + name: "valid integer prop", + param: &openapi3.Parameter{Name: "X-Param", In: "header", Schema: integerSchema}, + header: "X-Param:88", + found: true, + want: int64(88), + }, { name: "invalid integer prop", param: &openapi3.Parameter{Name: "X-Param", In: "header", Schema: objectOf("foo", integerSchema)}, @@ -893,7 +900,7 @@ func TestDecodeParameter(t *testing.T) { name: "integer", param: &openapi3.Parameter{Name: "X-Param", In: "cookie", Schema: integerSchema}, cookie: "X-Param:1", - want: float64(1), + want: int64(1), found: true, }, { @@ -1180,7 +1187,7 @@ func TestDecodeBody(t *testing.T) { WithProperty("a", openapi3.NewStringSchema()). WithProperty("b", openapi3.NewIntegerSchema()). WithProperty("c", openapi3.NewArraySchema().WithItems(openapi3.NewStringSchema())), - want: map[string]interface{}{"a": "a1", "b": float64(10), "c": []interface{}{"c1", "c2"}}, + want: map[string]interface{}{"a": "a1", "b": int64(10), "c": []interface{}{"c1", "c2"}}, }, { name: "urlencoded space delimited", @@ -1193,7 +1200,7 @@ func TestDecodeBody(t *testing.T) { encoding: map[string]*openapi3.Encoding{ "c": {Style: openapi3.SerializationSpaceDelimited, Explode: boolPtr(false)}, }, - want: map[string]interface{}{"a": "a1", "b": float64(10), "c": []interface{}{"c1", "c2"}}, + want: map[string]interface{}{"a": "a1", "b": int64(10), "c": []interface{}{"c1", "c2"}}, }, { name: "urlencoded pipe delimited", @@ -1206,7 +1213,7 @@ func TestDecodeBody(t *testing.T) { encoding: map[string]*openapi3.Encoding{ "c": {Style: openapi3.SerializationPipeDelimited, Explode: boolPtr(false)}, }, - want: map[string]interface{}{"a": "a1", "b": float64(10), "c": []interface{}{"c1", "c2"}}, + want: map[string]interface{}{"a": "a1", "b": int64(10), "c": []interface{}{"c1", "c2"}}, }, { name: "multipart",