Repository: getkin/kin-openapi
Pull request #711 (2022-12-16 05:25:32)

openapi3filter: parse integers with strconv.ParseInt instead of ParseFloat
parse integer primitives as int32 or int64, rather than float64


Patch:
diff --git a/openapi3filter/req_resp_decoder.go b/openapi3filter/req_resp_decoder.go
index 52c65af..870651c 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}
 		}


Test patch:
diff --git a/openapi3filter/issue625_test.go b/openapi3filter/issue625_test.go
index d9e5bae..5642a7e 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_test.go b/openapi3filter/req_resp_decoder_test.go
index 8bd62b1..709cdc9 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",