From 935c015c39e2b0d7bd379fff38eac5412c0e3255 Mon Sep 17 00:00:00 2001 From: A-Aravindhan Date: Fri, 6 Jul 2018 17:26:26 +0530 Subject: [PATCH 1/3] Fix for #742 Server with relative location are not converted to an absolute url --- .../io/swagger/v3/parser/OpenAPIV3Parser.java | 6 +-- .../v3/parser/util/OpenAPIDeserializer.java | 48 +++++++++++++++++-- .../v3/parser/test/OpenAPIV3ParserTest.java | 2 +- 3 files changed, 47 insertions(+), 9 deletions(-) diff --git a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/OpenAPIV3Parser.java b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/OpenAPIV3Parser.java index 0e5f57d7eb..256e276230 100644 --- a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/OpenAPIV3Parser.java +++ b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/OpenAPIV3Parser.java @@ -99,9 +99,9 @@ public OpenAPI read(String location, List auths, ParseOption return null; } - public SwaggerParseResult readWithInfo(JsonNode node) { + public SwaggerParseResult readWithInfo(String path, JsonNode node) { OpenAPIDeserializer ser = new OpenAPIDeserializer(); - return ser.deserialize(node); + return ser.deserialize(node, path); } private ObjectMapper getRightMapper(String data) { @@ -139,7 +139,7 @@ public SwaggerParseResult readWithInfo(String location, List ObjectMapper mapper = getRightMapper(data); JsonNode rootNode = mapper.readTree(data); LOGGER.debug("Parsed rootNode: {}", rootNode); - return readWithInfo(rootNode); + return readWithInfo(location, rootNode); } catch (SSLHandshakeException e) { SwaggerParseResult output = new SwaggerParseResult(); 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 3bdeb8f115..c277965936 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 @@ -48,7 +48,11 @@ import io.swagger.v3.core.util.Json; import org.apache.commons.lang3.StringUtils; +import java.io.File; import java.math.BigDecimal; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; @@ -97,10 +101,14 @@ public class OpenAPIDeserializer { public SwaggerParseResult deserialize(JsonNode rootNode) { + return deserialize(rootNode, null); + } + + public SwaggerParseResult deserialize(JsonNode rootNode, String path) { SwaggerParseResult result = new SwaggerParseResult(); try { ParseResult rootParse = new ParseResult(); - OpenAPI api = parseRoot(rootNode, rootParse); + OpenAPI api = parseRoot(rootNode, rootParse, path); result.setOpenAPI(api); result.setMessages(rootParse.getMessages()); } catch (Exception e) { @@ -110,7 +118,7 @@ public SwaggerParseResult deserialize(JsonNode rootNode) { return result; } - public OpenAPI parseRoot(JsonNode node, ParseResult result) { + public OpenAPI parseRoot(JsonNode node, ParseResult result, String path) { String location = ""; OpenAPI openAPI = new OpenAPI(); if (node.getNodeType().equals(JsonNodeType.OBJECT)) { @@ -145,7 +153,7 @@ public OpenAPI parseRoot(JsonNode node, ParseResult result) { ArrayNode array = getArray("servers", rootNode, false, location, result); if (array != null && array.size() > 0) { - openAPI.setServers(getServersList(array, String.format("%s.%s", location, "servers"), result)); + openAPI.setServers(getServersList(array, String.format("%s.%s", location, "servers"), result, path)); }else { Server defaultServer = new Server(); defaultServer.setUrl("/"); @@ -331,7 +339,7 @@ public Tag getTag(ObjectNode obj, String location, ParseResult result) { - public List getServersList(ArrayNode obj, String location, ParseResult result) { + public List getServersList(ArrayNode obj, String location, ParseResult result, String path) { List servers = new ArrayList<>(); if (obj == null) { @@ -352,8 +360,16 @@ public List getServersList(ArrayNode obj, String location, ParseResult r } return servers; } + + public List getServersList(ArrayNode obj, String location, ParseResult result) { + return getServersList(obj, location, result, null); + } + + public Server getServer(ObjectNode obj, String location, ParseResult result) { + return getServer(obj, location, result, null); + } - public Server getServer(ObjectNode obj, String location, ParseResult result) { + public Server getServer(ObjectNode obj, String location, ParseResult result, String path) { if (obj == null) { return null; } @@ -362,6 +378,18 @@ public Server getServer(ObjectNode obj, String location, ParseResult result) { String value = getString("url", obj, true, location, result); if(StringUtils.isNotBlank(value)) { + File file = new File(value); + if(!isValidURL(value) && !file.isAbsolute() && path != null){ + try { + final URI absURI = new URI(path); + if("http".equals(absURI.getScheme()) || "https".equals(absURI.getScheme())){ + value = absURI.resolve(new URI(value)).toString(); + } + } catch (URISyntaxException e) { + e.printStackTrace(); + } + + } server.setUrl(value); } @@ -393,6 +421,16 @@ public Server getServer(ObjectNode obj, String location, ParseResult result) { return server; } + + boolean isValidURL(String urlString){ + try { + URL url = new URL(urlString); + url.toURI(); + return true; + } catch (Exception exception) { + return false; + } + } public ServerVariables getServerVariables(ObjectNode obj, String location, ParseResult result){ ServerVariables serverVariables = new ServerVariables(); diff --git a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIV3ParserTest.java b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIV3ParserTest.java index 13dd389eac..cad5c1e6e6 100644 --- a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIV3ParserTest.java +++ b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIV3ParserTest.java @@ -1408,7 +1408,7 @@ public void readingSpecNodeShouldNotOverQuotingStringExample() throws Exception String yaml = Files.readFile(new File("src/test/resources/over-quoted-example.yaml")); JsonNode rootNode = Yaml.mapper().readValue(yaml, JsonNode.class); OpenAPIV3Parser parser = new OpenAPIV3Parser(); - OpenAPI openAPI = (parser.readWithInfo(rootNode)).getOpenAPI(); + OpenAPI openAPI = (parser.readWithInfo(null, rootNode)).getOpenAPI(); Map definitions = openAPI.getComponents().getSchemas(); assertEquals("NoQuotePlease", definitions.get("CustomerType").getExample()); From 21c0b5e31299cf73f16a150f27aa42b1f99dcc39 Mon Sep 17 00:00:00 2001 From: Jeremie Bresson Date: Wed, 11 Jul 2018 21:14:36 +0200 Subject: [PATCH 2/3] Proposed fixes for PR 754 https://github.com/swagger-api/swagger-parser/pull/754 --- .../java/io/swagger/v3/parser/util/OpenAPIDeserializer.java | 6 ++---- 1 file changed, 2 insertions(+), 4 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 c277965936..94f8fd1c16 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 @@ -48,7 +48,6 @@ import io.swagger.v3.core.util.Json; import org.apache.commons.lang3.StringUtils; -import java.io.File; import java.math.BigDecimal; import java.net.URI; import java.net.URISyntaxException; @@ -348,7 +347,7 @@ public List getServersList(ArrayNode obj, String location, ParseResult r } for (JsonNode item : obj) { if (item.getNodeType().equals(JsonNodeType.OBJECT)) { - Server server = getServer((ObjectNode) item, location, result); + Server server = getServer((ObjectNode) item, location, result, path); if (server != null) { servers.add(server); }else{ @@ -378,8 +377,7 @@ public Server getServer(ObjectNode obj, String location, ParseResult result, Str String value = getString("url", obj, true, location, result); if(StringUtils.isNotBlank(value)) { - File file = new File(value); - if(!isValidURL(value) && !file.isAbsolute() && path != null){ + if(!isValidURL(value) && path != null){ try { final URI absURI = new URI(path); if("http".equals(absURI.getScheme()) || "https".equals(absURI.getScheme())){ From 209994a826d2e77c3fcb9198f5e55ece0598dd89 Mon Sep 17 00:00:00 2001 From: Jeremie Bresson Date: Wed, 11 Jul 2018 21:16:17 +0200 Subject: [PATCH 3/3] Add test case for #742 https://github.com/swagger-api/swagger-parser/issues/742 --- .../v3/parser/test/NetworkReferenceTest.java | 30 +++++++++++++ .../src/test/resources/issue-742.json | 44 +++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 modules/swagger-parser-v3/src/test/resources/issue-742.json diff --git a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/NetworkReferenceTest.java b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/NetworkReferenceTest.java index 6cc854306f..c35cd35ebc 100644 --- a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/NetworkReferenceTest.java +++ b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/NetworkReferenceTest.java @@ -38,6 +38,7 @@ public class NetworkReferenceTest { private static String issue_335_json, issue_335_bar_json; private static String issue_407_json; private static String issue_411_server, issue_411_components; + private static String issue_742_json; static { try { @@ -63,6 +64,8 @@ public class NetworkReferenceTest { issue_411_server = readFile("src/test/resources/nested-network-references/issue-411-server.yaml"); issue_411_components = readFile("src/test/resources/nested-network-references/issue-411-remote2.yaml"); + + issue_742_json = readFile("src/test/resources/issue-742.json"); } catch(Exception e) { e.printStackTrace(); @@ -256,6 +259,33 @@ public void testIssue411() throws Exception { assertTrue(swagger.getComponents().getSchemas().get("Error") instanceof Schema); } + + @Test + public void testIssue742() throws Exception { + final List< AuthorizationValue > auths = new ArrayList<>(); + + new Expectations() {{ + remoteUrl.urlToString("http://www.example.io/one/two/swagger.json", auths); + result = issue_742_json; + }}; + + OpenAPIV3Parser parser = new OpenAPIV3Parser(); + ParseOptions options = new ParseOptions(); + options.setResolve(true); + SwaggerParseResult result = parser.readLocation("http://www.example.io/one/two/swagger.json", auths, options); + + Assert.assertNotNull(result.getOpenAPI()); + Assert.assertNotNull(result.getOpenAPI().getServers()); + Assert.assertEquals(result.getOpenAPI().getServers().size(), 4); + Assert.assertEquals(result.getOpenAPI().getServers().get(0).getDescription(), "An absolute path"); + Assert.assertEquals(result.getOpenAPI().getServers().get(0).getUrl(), "https://api.absolute.org/v2"); + Assert.assertEquals(result.getOpenAPI().getServers().get(1).getDescription(), "Server relative to root path"); + Assert.assertEquals(result.getOpenAPI().getServers().get(1).getUrl(), "http://www.example.io/api/v2"); + Assert.assertEquals(result.getOpenAPI().getServers().get(2).getDescription(), "Server relative path 1"); + Assert.assertEquals(result.getOpenAPI().getServers().get(2).getUrl(), "http://www.example.io/one/two/path/v2"); + Assert.assertEquals(result.getOpenAPI().getServers().get(3).getDescription(), "Server relative path 2"); + Assert.assertEquals(result.getOpenAPI().getServers().get(3).getUrl(), "http://www.example.io/one/v2"); + } static String readFile(String name) throws Exception { return new String(Files.readAllBytes(new File(name).toPath()), Charset.forName("UTF-8")); diff --git a/modules/swagger-parser-v3/src/test/resources/issue-742.json b/modules/swagger-parser-v3/src/test/resources/issue-742.json new file mode 100644 index 0000000000..2532e464b1 --- /dev/null +++ b/modules/swagger-parser-v3/src/test/resources/issue-742.json @@ -0,0 +1,44 @@ +{ + "openapi": "3.0.1", + "servers": [ + { + "description": "An absolute path", + "url": "https://api.absolute.org/v2" + }, + { + "description": "Server relative to root path", + "url": "/api/v2" + }, + { + "description": "Server relative path 1", + "url": "path/v2" + }, + { + "description": "Server relative path 2", + "url": "../v2" + } + ], + "info": { + "description": "This is a sample server", + "version": "1.0.0", + "title": "Issue 742 API", + "license": { + "name": "Apache-2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0.html" + } + }, + "paths": { + "/ping": { + "get": { + "summary": "Some ping operation", + "description": "Some ping operation", + "operationId": "doPing", + "responses": { + "201": { + "description": "OK" + } + } + } + } + } + } \ No newline at end of file