From b35c8c24164702f11d13d9f7e3cb4dd0879fa6f2 Mon Sep 17 00:00:00 2001 From: Kerry Kimbrough Date: Wed, 20 Apr 2022 21:09:08 -0500 Subject: [PATCH 1/2] getMediaType: Report an error for any encoding property not defined in the schema. --- .../v3/parser/util/OpenAPIDeserializer.java | 8 ++- .../parser/util/OpenAPIDeserializerTest.java | 60 +++++++++++++++++++ 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/OpenAPIDeserializer.java b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/OpenAPIDeserializer.java index b15ab81205..7a17c28b53 100644 --- a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/OpenAPIDeserializer.java +++ b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/OpenAPIDeserializer.java @@ -1070,8 +1070,12 @@ public MediaType getMediaType(ObjectNode contentNode, String location, ParseResu ObjectNode encodingObject = getObject("encoding", contentNode, false, location, result); if (encodingObject != null) { - mediaType.setEncoding(getEncodingMap(encodingObject, String.format("%s.%s", location, "encoding"), - result)); + String encodingLocation = String.format("%s.%s", location, "encoding"); + mediaType.setEncoding(getEncodingMap(encodingObject, encodingLocation, result)); + + mediaType.getEncoding().keySet().stream() + .filter( ep -> Optional.ofNullable( mediaType.getSchema().getProperties()).map( p -> !p.containsKey( ep)).orElse( true)) + .forEach( ep -> result.extra( encodingLocation, ep, encodingObject)); } Map extensions = getExtensions(contentNode); if (extensions != null && extensions.size() > 0) { diff --git a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/util/OpenAPIDeserializerTest.java b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/util/OpenAPIDeserializerTest.java index 83ec3a719e..74473151ca 100644 --- a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/util/OpenAPIDeserializerTest.java +++ b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/util/OpenAPIDeserializerTest.java @@ -1277,6 +1277,66 @@ public void testBodyContent() { assertEquals( result.getMessages().size(), 2, "Messages"); } + @Test + public void testEncodingNotApplicable() { + String json = + "{" + + " \"openapi\": \"3.0.0\"," + + " \"info\": {" + + " \"title\": \"Encodings\"," + + " \"version\": \"0.0.0\"" + + " }," + + " \"paths\": {" + + " \"/resource\": {" + + " \"post\": {" + + " \"requestBody\": {" + + " \"content\": {" + + " \"multipart/form-data\": {" + + " \"schema\": {" + + " \"type\": \"object\"," + + " \"properties\": {" + + " \"X\": {" + + " \"type\": \"integer\"" + + " }," + + " \"Y\": {" + + " \"type\": \"integer\"" + + " }" + + " }" + + " }," + + " \"encoding\": {" + + " \"A\": {" + + " \"contentType\": \"application/json\"" + + " }," + + " \"Z\": {" + + " \"contentType\": \"text/plain\"" + + " }" + + " }" + + " }" + + " }" + + " }," + + " \"responses\": {" + + " \"default\": {" + + " \"description\": \"None\"" + + " }" + + " }" + + " }" + + " }" + + " }" + + "}" + ; + OpenAPIV3Parser parser = new OpenAPIV3Parser(); + SwaggerParseResult result = parser.readContents(json, null, null); + + assertEquals + ( result.getMessages(), + + Arrays.asList + ( "attribute paths.'/resource'(post).requestBody.content.'multipart/form-data'.encoding.A is unexpected", + "attribute paths.'/resource'(post).requestBody.content.'multipart/form-data'.encoding.Z is unexpected"), + + "Error messages"); + } + @Test public void testStyleInvalid() { String json = From c8b9e8e98bb6a5f0f493013285d397e9b8b656c0 Mon Sep 17 00:00:00 2001 From: Kerry Kimbrough Date: Thu, 16 Jun 2022 16:51:06 -0500 Subject: [PATCH 2/2] getMediaType: Handle correctly when schema is undefined or defined by $ref --- .../v3/parser/util/OpenAPIDeserializer.java | 21 +++- .../parser/util/OpenAPIDeserializerTest.java | 101 +++++++++++++++++- 2 files changed, 114 insertions(+), 8 deletions(-) diff --git a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/OpenAPIDeserializer.java b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/OpenAPIDeserializer.java index 69ac4fa41e..95d3d20e41 100644 --- a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/OpenAPIDeserializer.java +++ b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/OpenAPIDeserializer.java @@ -72,6 +72,7 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; +import static java.util.Collections.emptySet; public class OpenAPIDeserializer { @@ -1354,15 +1355,27 @@ public MediaType getMediaType(ObjectNode contentNode, String location, ParseResu mediaType.setSchema(getSchema(schemaObject, String.format("%s.%s", location, "schema"), result)); } - ObjectNode encodingObject = getObject("encoding", contentNode, false, location, result); if (encodingObject != null) { String encodingLocation = String.format("%s.%s", location, "encoding"); mediaType.setEncoding(getEncodingMap(encodingObject, encodingLocation, result)); - mediaType.getEncoding().keySet().stream() - .filter( ep -> Optional.ofNullable( mediaType.getSchema().getProperties()).map( p -> !p.containsKey( ep)).orElse( true)) - .forEach( ep -> result.extra( encodingLocation, ep, encodingObject)); + // Given all properties defined for this media type object... + Set mediaTypeProperties = + mediaType.getSchema() == null? + emptySet() : + + mediaType.getSchema().get$ref() == null? + Optional.ofNullable( mediaType.getSchema().getProperties()).map( Map::keySet).orElse( emptySet()) : + + null; + + if( mediaTypeProperties != null) { + // ... report an error if an encoding is specified for an undefined property + mediaType.getEncoding().keySet().stream() + .filter( ep -> !mediaTypeProperties.contains( ep)) + .forEach( ep -> result.extra( encodingLocation, ep, encodingObject)); + } } Map extensions = getExtensions(contentNode); if (extensions != null && extensions.size() > 0) { diff --git a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/util/OpenAPIDeserializerTest.java b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/util/OpenAPIDeserializerTest.java index 8080dd64a4..5b2bb451d3 100644 --- a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/util/OpenAPIDeserializerTest.java +++ b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/util/OpenAPIDeserializerTest.java @@ -1287,7 +1287,7 @@ public void testEncodingNotApplicable() { + " \"version\": \"0.0.0\"" + " }," + " \"paths\": {" - + " \"/resource\": {" + + " \"/properties\": {" + " \"post\": {" + " \"requestBody\": {" + " \"content\": {" @@ -1304,7 +1304,7 @@ public void testEncodingNotApplicable() { + " }" + " }," + " \"encoding\": {" - + " \"A\": {" + + " \"X\": {" + " \"contentType\": \"application/json\"" + " }," + " \"Z\": {" @@ -1320,6 +1320,96 @@ public void testEncodingNotApplicable() { + " }" + " }" + " }" + + " }," + + " \"/propertiesNone\": {" + + " \"post\": {" + + " \"requestBody\": {" + + " \"content\": {" + + " \"multipart/form-data\": {" + + " \"schema\": {" + + " \"type\": \"object\"" + + " }," + + " \"encoding\": {" + + " \"X\": {" + + " \"contentType\": \"application/json\"" + + " }," + + " \"Z\": {" + + " \"contentType\": \"text/plain\"" + + " }" + + " }" + + " }" + + " }" + + " }," + + " \"responses\": {" + + " \"default\": {" + + " \"description\": \"None\"" + + " }" + + " }" + + " }" + + " }," + + " \"/schemaNone\": {" + + " \"post\": {" + + " \"requestBody\": {" + + " \"content\": {" + + " \"application/x-www-form-urlencoded\": {" + + " \"encoding\": {" + + " \"X\": {" + + " \"contentType\": \"application/json\"" + + " }," + + " \"Z\": {" + + " \"contentType\": \"text/plain\"" + + " }" + + " }" + + " }" + + " }" + + " }," + + " \"responses\": {" + + " \"default\": {" + + " \"description\": \"None\"" + + " }" + + " }" + + " }" + + " }," + + " \"/schemaRef\": {" + + " \"post\": {" + + " \"requestBody\": {" + + " \"content\": {" + + " \"application/x-www-form-urlencoded\": {" + + " \"schema\": {" + + " \"$ref\": \"#/components/schemas/encoded\"" + + " }," + + " \"encoding\": {" + + " \"X\": {" + + " \"contentType\": \"application/json\"" + + " }," + + " \"Z\": {" + + " \"contentType\": \"text/plain\"" + + " }" + + " }" + + " }" + + " }" + + " }," + + " \"responses\": {" + + " \"default\": {" + + " \"description\": \"None\"" + + " }" + + " }" + + " }" + + " }" + + " }," + + " \"components\": {" + + " \"schemas\": {" + + " \"encoded\": {" + + " \"type\": \"object\"," + + " \"properties\": {" + + " \"X\": {" + + " \"type\": \"integer\"" + + " }," + + " \"Y\": {" + + " \"type\": \"integer\"" + + " }" + + " }" + + " }" + " }" + " }" + "}" @@ -1331,8 +1421,11 @@ public void testEncodingNotApplicable() { ( result.getMessages(), Arrays.asList - ( "attribute paths.'/resource'(post).requestBody.content.'multipart/form-data'.encoding.A is unexpected", - "attribute paths.'/resource'(post).requestBody.content.'multipart/form-data'.encoding.Z is unexpected"), + ( "attribute paths.'/properties'(post).requestBody.content.'multipart/form-data'.encoding.Z is unexpected", + "attribute paths.'/propertiesNone'(post).requestBody.content.'multipart/form-data'.encoding.X is unexpected", + "attribute paths.'/propertiesNone'(post).requestBody.content.'multipart/form-data'.encoding.Z is unexpected", + "attribute paths.'/schemaNone'(post).requestBody.content.'application/x-www-form-urlencoded'.encoding.X is unexpected", + "attribute paths.'/schemaNone'(post).requestBody.content.'application/x-www-form-urlencoded'.encoding.Z is unexpected"), "Error messages"); }