Skip to content

fix for root traversals #321

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 27, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,17 @@ public void processDefinitions() {
}

Set<String> keySet = new HashSet<>();
keySet.addAll(definitions.keySet());

for (String modelName : keySet) {
// the definitions can grow as we resolve references
while(definitions.keySet().size() > keySet.size()) {
processDefinitions(keySet, definitions);
}
}

public void processDefinitions(Set<String> modelKeys, Map<String, Model> definitions) {
modelKeys.addAll(definitions.keySet());

for (String modelName : modelKeys) {
final Model model = definitions.get(modelName);

String originalRef = model instanceof RefModel ? ((RefModel) model).get$ref() : null;
Expand All @@ -48,7 +56,6 @@ public void processDefinitions() {
final Model resolvedModel = definitions.remove(renamedRef);
definitions.put(modelName, resolvedModel);
}

}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import io.swagger.parser.ResolverCache;
import org.slf4j.LoggerFactory;

import java.net.URI;
import java.util.HashMap;
import java.util.Map;

Expand Down Expand Up @@ -95,9 +96,50 @@ public String processRefToExternalDefinition(String $ref, RefFormat refFormat) {

private void processRefProperty(RefProperty subRef, String externalFile) {
if (isAnExternalRefFormat(subRef.getRefFormat())) {
subRef.set$ref(processRefToExternalDefinition(subRef.get$ref(), subRef.getRefFormat()));
String $ref = constructRef(subRef, externalFile);
subRef.set$ref($ref);
if($ref.startsWith("."))
processRefToExternalDefinition($ref, RefFormat.RELATIVE);
else {
processRefToExternalDefinition($ref, RefFormat.URL);
}

} else {
processRefToExternalDefinition(externalFile + subRef.get$ref(), RefFormat.RELATIVE);
}
}

protected String constructRef(RefProperty refProperty, String rootLocation) {
String ref = refProperty.get$ref();
return join(rootLocation, ref);
}

public static String join(String source, String fragment) {
try {
boolean isRelative = false;
if(source.startsWith("/") || source.startsWith(".")) {
isRelative = true;
}
URI uri = new URI(source);

if(!source.endsWith("/") && (fragment.startsWith("./") && "".equals(uri.getPath()))) {
uri = new URI(source + "/");
}
else if("".equals(uri.getPath()) && !fragment.startsWith("/")) {
uri = new URI(source + "/");
}
URI f = new URI(fragment);

URI resolved = uri.resolve(f);

URI normalized = resolved.normalize();
if(Character.isAlphabetic(normalized.toString().charAt(0)) && isRelative) {
return "./" + normalized.toString();
}
return normalized.toString();
}
catch(Exception e) {
return source;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package io.swagger.parser;

import io.swagger.models.Model;
import io.swagger.models.Operation;
import io.swagger.models.Path;
import io.swagger.models.Swagger;
import io.swagger.models.properties.Property;
import io.swagger.models.properties.RefProperty;
import io.swagger.parser.util.SwaggerDeserializationResult;
import io.swagger.util.Json;
import org.testng.annotations.Test;

import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.*;

public class FileReferenceTests {
@Test
Expand Down Expand Up @@ -77,12 +77,34 @@ public void testIssue314() {
Path path = swagger.getPath("/events");
assertNotNull(path.getGet());

Json.prettyPrint(result);
Operation get = path.getGet();
assertEquals(get.getOperationId(), "getEvents");
assertTrue(swagger.getDefinitions().size() == 3);
assertTrue(swagger.getDefinitions().get("Foobar").getProperties().size() == 1);
assertTrue(swagger.getDefinitions().get("StatusResponse").getProperties().size() == 1);
assertTrue(swagger.getDefinitions().get("Paging").getProperties().size() == 1);
}

@Test
public void testIssue316() {
SwaggerDeserializationResult result = new SwaggerParser().readWithInfo("./src/test/resources/nested-file-references/issue-316.yaml", null, true);
assertNotNull(result.getSwagger());

Swagger swagger = result.getSwagger();
assertNotNull(swagger.getPath("/events"));
Path path = swagger.getPath("/events");
assertNotNull(path.getGet());
Operation get = path.getGet();
assertEquals(get.getOperationId(), "getEvents");
assertTrue(swagger.getDefinitions().size() == 3);
assertTrue(swagger.getDefinitions().get("Foobar").getProperties().size() == 1);
assertTrue(swagger.getDefinitions().get("StatusResponse").getProperties().size() == 1);
assertTrue(swagger.getDefinitions().get("Paging2").getProperties().size() == 2);
Model model = swagger.getDefinitions().get("Paging2");

Property property = model.getProperties().get("foobar");
assertTrue(property instanceof RefProperty);
RefProperty ref = (RefProperty) property;
assertEquals(ref.get$ref(), "#/definitions/Foobar");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,6 @@ public void testLoadRecursiveExternalDef() throws Exception {
SwaggerParser parser = new SwaggerParser();
final Swagger swagger = parser.read("src/test/resources/file-reference-to-recursive-defs/b.yaml");

Json.prettyPrint(swagger);
Map<String, Model> definitions = swagger.getDefinitions();
assertEquals(((RefProperty) ((ArrayProperty) definitions.get("v").getProperties().get("children")).getItems()).get$ref(), "#/definitions/v");
assertTrue(!definitions.containsKey("y"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ public void testNestedExternalRefs(@Injectable final Model mockedModel){

String actualRef = new ExternalRefProcessor(cache, testedSwagger).processRefToExternalDefinition(customerURL, refFormat);

assertTrue(testedSwagger.getDefinitions().get("Customer")!=null);
assertTrue(testedSwagger.getDefinitions().get("Customer")!=null);
assertTrue(testedSwagger.getDefinitions().get("Contact")!=null);
assertTrue(testedSwagger.getDefinitions().get("Address")!=null);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import io.swagger.models.ModelImpl;
import io.swagger.models.auth.AuthorizationValue;
import io.swagger.models.refs.RefFormat;
import io.swagger.parser.processors.ExternalRefProcessor;
import mockit.Injectable;
import mockit.Mocked;
import mockit.StrictExpectations;
Expand Down Expand Up @@ -251,4 +252,33 @@ public void testReadExternalRef_OnClasspath(@Mocked Files files,
assertEquals(actualResult, expectedResult);

}

@Test
public void testPathJoin1() {
// simple
assertEquals(ExternalRefProcessor.join("http://foo.bar.com", "fun"), "http://foo.bar.com/fun");
assertEquals(ExternalRefProcessor.join("http://foo.bar.com/", "fun"), "http://foo.bar.com/fun");
assertEquals(ExternalRefProcessor.join("http://foo.bar.com/", "/fun"), "http://foo.bar.com/fun");
assertEquals(ExternalRefProcessor.join("http://foo.bar.com", "/fun"), "http://foo.bar.com/fun");

// relative to host
assertEquals(ExternalRefProcessor.join("http://foo.bar.com/foo/bar", "/fun"), "http://foo.bar.com/fun");
assertEquals(ExternalRefProcessor.join("http://foo.bar.com/foo/bar#/baz/bat", "/fun"), "http://foo.bar.com/fun");
assertEquals(ExternalRefProcessor.join("http://foo.bar.com/foo/bar#/baz/bat", "/fun#for/all"), "http://foo.bar.com/fun#for/all");

// relative
assertEquals(ExternalRefProcessor.join("http://foo.bar.com", "./fun"), "http://foo.bar.com/fun");
assertEquals(ExternalRefProcessor.join("http://foo.bar.com/veryFun", "./fun"), "http://foo.bar.com/fun");
assertEquals(ExternalRefProcessor.join("http://foo.bar.com/veryFun/", "../fun#nothing"), "http://foo.bar.com/fun#nothing");
assertEquals(ExternalRefProcessor.join("http://foo.bar.com/veryFun/notFun", "../fun#/it/is/fun"), "http://foo.bar.com/fun#/it/is/fun");

// with file extensions
assertEquals(ExternalRefProcessor.join("http://foo.bar.com/baz/bat.yaml", "../fun/times.yaml"), "http://foo.bar.com/fun/times.yaml");

// hashes
assertEquals(ExternalRefProcessor.join("http://foo.bar.com/veryFun/", "../fun#/it/is/fun"), "http://foo.bar.com/fun#/it/is/fun");

// relative locations
assertEquals(ExternalRefProcessor.join("./foo#/definitions/Foo", "./bar#/definitions/Bar"), "./bar#/definitions/Bar");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import io.swagger.parser.SwaggerParser;
import io.swagger.parser.SwaggerResolver;
import io.swagger.util.Json;
import io.swagger.util.Yaml;
import org.testng.Assert;
import org.testng.annotations.Test;

Expand Down Expand Up @@ -1148,6 +1147,5 @@ public void testPR246() throws Exception {

assertTrue(composed.getChild() instanceof ModelImpl);
assertTrue(composed.getInterfaces().size() == 2);
Yaml.prettyPrint(swagger);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Paging2:
properties:
total_items:
type: integer
foobar:
$ref: '../common2/bar.yaml#/Foobar'
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
get:
description: A list of events
operationId: getEvents
responses:
200:
description: OK
schema:
type: object
properties:
paging:
$ref: './common/paging2.yaml#/Paging2'
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
swagger: '2.0'
info:
title: Test API
version: '1'
host: example.com
basePath: /api/v1
schemes:
- https
consumes:
- application/json; charset=utf-8
produces:
- application/json; charset=utf-8

paths:
/events:
$ref: './eventsWithPaging.yaml'

definitions:
StatusResponse:
properties:
http_code:
type: integer