Search in sources :

Example 6 with ResolverCache

use of io.swagger.v3.parser.ResolverCache in project swagger-parser by swagger-api.

the class ResolverCacheTest method testLoadExternalRefResponseWithNoContent.

@Test
public void testLoadExternalRefResponseWithNoContent() throws Exception {
    final RefFormat format = RefFormat.URL;
    final String ref = "http://my.company.com/path/to/main.yaml";
    final String contentsOfExternalFile = "openapi: 3.0.0\n" + "\n" + "info:\n" + "  version: 1.0.0\n" + "  title: Response include test case child\n" + "\n" + "components:\n" + "  responses:\n" + "    200:\n" + "      description: Success\n";
    new Expectations() {

        {
            RefUtils.readExternalUrlRef(ref, format, auths, "http://my.company.com/path/parent.json");
            times = 1;
            result = contentsOfExternalFile;
        }
    };
    ResolverCache cache = new ResolverCache(openAPI, auths, "http://my.company.com/path/parent.json");
    ApiResponse response = cache.loadRef(ref + "#/components/responses/200", RefFormat.URL, ApiResponse.class);
    assertNotNull(response);
    assertEquals(response.getDescription(), "Success");
    assertNull(response.getContent());
}
Also used : Expectations(mockit.Expectations) RefFormat(io.swagger.v3.parser.models.RefFormat) ResolverCache(io.swagger.v3.parser.ResolverCache) ApiResponse(io.swagger.v3.oas.models.responses.ApiResponse) Test(org.testng.annotations.Test)

Example 7 with ResolverCache

use of io.swagger.v3.parser.ResolverCache in project swagger-parser by swagger-api.

the class ResolverCacheTest method testLoadInternalResponseRefWithSpaces.

@Test
public void testLoadInternalResponseRefWithSpaces(@Injectable ApiResponse mockedResponse) throws Exception {
    OpenAPI openAPI = new OpenAPI();
    openAPI.components(new Components().addResponses("foo bar", mockedResponse));
    ResolverCache cache = new ResolverCache(openAPI, auths, null);
    ApiResponse actualResult = cache.loadRef("#/components/responses/foo bar", RefFormat.INTERNAL, ApiResponse.class);
    assertEquals(actualResult, mockedResponse);
}
Also used : Components(io.swagger.v3.oas.models.Components) ResolverCache(io.swagger.v3.parser.ResolverCache) OpenAPI(io.swagger.v3.oas.models.OpenAPI) ApiResponse(io.swagger.v3.oas.models.responses.ApiResponse) Test(org.testng.annotations.Test)

Example 8 with ResolverCache

use of io.swagger.v3.parser.ResolverCache in project swagger-parser by swagger-api.

the class OpenAPIDeserializer method getSchema.

public Schema getSchema(ObjectNode node, String location, ParseResult result) {
    if (node == null) {
        return null;
    }
    // Added to handle NPE from ResolverCache when Trying to dereference a schema
    if (result == null) {
        result = new ParseResult();
        result.setAllowEmptyStrings(true);
    }
    Schema schema = null;
    ArrayNode oneOfArray = getArray("oneOf", node, false, location, result);
    ArrayNode allOfArray = getArray("allOf", node, false, location, result);
    ArrayNode anyOfArray = getArray("anyOf", node, false, location, result);
    ObjectNode itemsNode = getObject("items", node, false, location, result);
    if ((allOfArray != null) || (anyOfArray != null) || (oneOfArray != null)) {
        ComposedSchema composedSchema = new ComposedSchema();
        if (allOfArray != null) {
            for (JsonNode n : allOfArray) {
                if (n.isObject()) {
                    schema = getSchema((ObjectNode) n, location, result);
                    composedSchema.addAllOfItem(schema);
                }
            }
            schema = composedSchema;
        }
        if (anyOfArray != null) {
            for (JsonNode n : anyOfArray) {
                if (n.isObject()) {
                    schema = getSchema((ObjectNode) n, location, result);
                    composedSchema.addAnyOfItem(schema);
                }
            }
            schema = composedSchema;
        }
        if (oneOfArray != null) {
            for (JsonNode n : oneOfArray) {
                if (n.isObject()) {
                    schema = getSchema((ObjectNode) n, location, result);
                    composedSchema.addOneOfItem(schema);
                }
            }
            schema = composedSchema;
        }
    }
    if (itemsNode != null) {
        ArraySchema items = new ArraySchema();
        if (itemsNode.getNodeType().equals(JsonNodeType.OBJECT)) {
            items.setItems(getSchema(itemsNode, location, result));
        } else if (itemsNode.getNodeType().equals(JsonNodeType.ARRAY)) {
            for (JsonNode n : itemsNode) {
                if (n.isValueNode()) {
                    items.setItems(getSchema(itemsNode, location, result));
                }
            }
        }
        schema = items;
    }
    Boolean additionalPropertiesBoolean = getBoolean("additionalProperties", node, false, location, result);
    ObjectNode additionalPropertiesObject = additionalPropertiesBoolean == null ? getObject("additionalProperties", node, false, location, result) : null;
    Object additionalProperties = additionalPropertiesObject != null ? getSchema(additionalPropertiesObject, location, result) : additionalPropertiesBoolean;
    if (additionalProperties != null) {
        if (schema == null) {
            schema = additionalProperties.equals(Boolean.FALSE) ? new ObjectSchema() : new MapSchema();
        }
        schema.setAdditionalProperties(additionalProperties);
    }
    if (schema == null) {
        schema = SchemaTypeUtil.createSchemaByType(node);
    }
    JsonNode ref = node.get("$ref");
    if (ref != null) {
        if (ref.getNodeType().equals(JsonNodeType.STRING)) {
            if (location.startsWith("paths")) {
                try {
                    String[] components = ref.asText().split("#/components");
                    if ((ref.asText().startsWith("#/components")) && (components.length > 1)) {
                        String[] childComponents = components[1].split("/");
                        String[] newChildComponents = Arrays.copyOfRange(childComponents, 1, childComponents.length);
                        boolean isValidComponent = ReferenceValidator.valueOf(newChildComponents[0]).validateComponent(this.components, newChildComponents[1]);
                        if (!isValidComponent) {
                            result.missing(location, ref.asText());
                        }
                    }
                } catch (Exception e) {
                    result.missing(location, ref.asText());
                }
            }
            String mungedRef = mungedRef(ref.textValue());
            if (mungedRef != null) {
                schema.set$ref(mungedRef);
            } else {
                schema.set$ref(ref.asText());
            }
            return schema;
        } else {
            result.invalidType(location, "$ref", "string", node);
            return null;
        }
    }
    String value = getString("title", node, false, location, result);
    if ((result.isAllowEmptyStrings() && value != null) || (!result.isAllowEmptyStrings() && !StringUtils.isBlank(value))) {
        schema.setTitle(value);
    }
    ObjectNode discriminatorNode = getObject("discriminator", node, false, location, result);
    if (discriminatorNode != null) {
        schema.setDiscriminator(getDiscriminator(discriminatorNode, location, result));
    }
    BigDecimal bigDecimal = getBigDecimal("multipleOf", node, false, location, result);
    if (bigDecimal != null) {
        if (bigDecimal.compareTo(BigDecimal.ZERO) > 0) {
            schema.setMultipleOf(bigDecimal);
        } else {
            result.warning(location, "multipleOf value must be > 0");
        }
    }
    bigDecimal = getBigDecimal("maximum", node, false, location, result);
    if (bigDecimal != null) {
        schema.setMaximum(bigDecimal);
    }
    Boolean bool = getBoolean("exclusiveMaximum", node, false, location, result);
    if (bool != null) {
        schema.setExclusiveMaximum(bool);
    }
    bigDecimal = getBigDecimal("minimum", node, false, location, result);
    if (bigDecimal != null) {
        schema.setMinimum(bigDecimal);
    }
    bool = getBoolean("exclusiveMinimum", node, false, location, result);
    if (bool != null) {
        schema.setExclusiveMinimum(bool);
    }
    Integer integer = getInteger("minLength", node, false, location, result);
    if (integer != null) {
        schema.setMinLength(integer);
    }
    integer = getInteger("maxLength", node, false, location, result);
    if (integer != null) {
        schema.setMaxLength(integer);
    }
    String pattern = getString("pattern", node, false, location, result);
    if (result.isAllowEmptyStrings() && pattern != null) {
        schema.setPattern(pattern);
    }
    integer = getInteger("maxItems", node, false, location, result);
    if (integer != null) {
        schema.setMaxItems(integer);
    }
    integer = getInteger("minItems", node, false, location, result);
    if (integer != null) {
        schema.setMinItems(integer);
    }
    bool = getBoolean("uniqueItems", node, false, location, result);
    if (bool != null) {
        schema.setUniqueItems(bool);
    }
    integer = getInteger("maxProperties", node, false, location, result);
    if (integer != null) {
        schema.setMaxProperties(integer);
    }
    integer = getInteger("minProperties", node, false, location, result);
    if (integer != null) {
        schema.setMinProperties(integer);
    }
    ArrayNode required = getArray("required", node, false, location, result);
    if (required != null) {
        List<String> requiredList = new ArrayList<>();
        for (JsonNode n : required) {
            if (n.getNodeType().equals(JsonNodeType.STRING)) {
                requiredList.add(((TextNode) n).textValue());
            } else {
                result.invalidType(location, "required", "string", n);
            }
        }
        if (requiredList.size() > 0) {
            schema.setRequired(requiredList);
        }
    }
    ArrayNode enumArray = getArray("enum", node, false, location, result);
    if (enumArray != null) {
        for (JsonNode n : enumArray) {
            if (n.isNumber()) {
                schema.addEnumItemObject(n.numberValue());
            } else if (n.isBoolean()) {
                schema.addEnumItemObject(n.booleanValue());
            } else if (n.isValueNode()) {
                try {
                    schema.addEnumItemObject(getDecodedObject(schema, n.asText(null)));
                } catch (ParseException e) {
                    result.invalidType(location, String.format("enum=`%s`", e.getMessage()), schema.getFormat(), n);
                }
            } else if (n.isContainerNode()) {
                schema.addEnumItemObject(n.isNull() ? null : n);
            } else {
                result.invalidType(location, "enum", "value", n);
            }
        }
    }
    value = getString("type", node, false, location, result);
    if (StringUtils.isBlank(schema.getType())) {
        if ((result.isAllowEmptyStrings() && value != null) || (!result.isAllowEmptyStrings() && !StringUtils.isBlank(value))) {
            schema.setType(value);
        } else {
            // may have an enum where type can be inferred
            JsonNode enumNode = node.get("enum");
            if (enumNode != null && enumNode.isArray()) {
                String type = inferTypeFromArray((ArrayNode) enumNode);
                schema.setType(type);
            }
        }
        if ("array".equals(schema.getType()) && !(schema instanceof ArraySchema && ((ArraySchema) schema).getItems() != null)) {
            result.missing(location, "items");
        }
    }
    ObjectNode notObj = getObject("not", node, false, location, result);
    if (notObj != null) {
        Schema not = getSchema(notObj, location, result);
        if (not != null) {
            schema.setNot(not);
        }
    }
    Map<String, Schema> properties = new LinkedHashMap<>();
    ObjectNode propertiesObj = getObject("properties", node, false, location, result);
    Schema property = null;
    Set<String> keys = getKeys(propertiesObj);
    for (String name : keys) {
        JsonNode propertyValue = propertiesObj.get(name);
        if (!propertyValue.getNodeType().equals(JsonNodeType.OBJECT)) {
            result.invalidType(location, "properties", "object", propertyValue);
        } else {
            if (propertiesObj != null) {
                property = getSchema((ObjectNode) propertyValue, location, result);
                if (property != null) {
                    properties.put(name, property);
                }
            }
        }
    }
    if (propertiesObj != null) {
        schema.setProperties(properties);
    }
    value = getString("description", node, false, location, result);
    if ((result.isAllowEmptyStrings() && value != null) || (!result.isAllowEmptyStrings() && !StringUtils.isBlank(value))) {
        schema.setDescription(value);
    }
    value = getString("format", node, false, location, result);
    if ((result.isAllowEmptyStrings() && value != null) || (!result.isAllowEmptyStrings() && !StringUtils.isBlank(value))) {
        schema.setFormat(value);
    }
    // sets default value according to the schema type
    if (node.get("default") != null) {
        if (!StringUtils.isBlank(schema.getType())) {
            if (schema.getType().equals("array")) {
                ArrayNode array = getArray("default", node, false, location, result);
                if (array != null) {
                    schema.setDefault(array);
                }
            } else if (schema.getType().equals("string")) {
                value = getString("default", node, false, location, result);
                if ((result.isAllowEmptyStrings() && value != null) || (!result.isAllowEmptyStrings() && !StringUtils.isBlank(value))) {
                    try {
                        schema.setDefault(getDecodedObject(schema, value));
                    } catch (ParseException e) {
                        result.invalidType(location, String.format("default=`%s`", e.getMessage()), schema.getFormat(), node);
                    }
                }
            } else if (schema.getType().equals("boolean")) {
                bool = getBoolean("default", node, false, location, result);
                if (bool != null) {
                    schema.setDefault(bool);
                }
            } else if (schema.getType().equals("object")) {
                Object object = getObject("default", node, false, location, result);
                if (object != null) {
                    schema.setDefault(object);
                }
            } else if (schema.getType().equals("integer")) {
                Integer number = getInteger("default", node, false, location, result);
                if (number != null) {
                    schema.setDefault(number);
                }
            } else if (schema.getType().equals("number")) {
                BigDecimal number = getBigDecimal("default", node, false, location, result);
                if (number != null) {
                    schema.setDefault(number);
                }
            }
        }
    }
    bool = getBoolean("nullable", node, false, location, result);
    if (bool != null) {
        schema.setNullable(bool);
    }
    bool = getBoolean("readOnly", node, false, location, result);
    if (bool != null) {
        schema.setReadOnly(bool);
    }
    bool = getBoolean("writeOnly", node, false, location, result);
    if (bool != null) {
        schema.setWriteOnly(bool);
    }
    bool = Optional.ofNullable(getBoolean("writeOnly", node, false, location, result)).orElse(false) && Optional.ofNullable(getBoolean("readOnly", node, false, location, result)).orElse(false);
    if (bool == true) {
        result.warning(location, " writeOnly and readOnly are both present");
    }
    ObjectNode xmlNode = getObject("xml", node, false, location, result);
    if (xmlNode != null) {
        XML xml = getXml(xmlNode, location, result);
        if (xml != null) {
            schema.setXml(xml);
        }
    }
    ObjectNode externalDocs = getObject("externalDocs", node, false, location, result);
    if (externalDocs != null) {
        ExternalDocumentation docs = getExternalDocs(externalDocs, location, result);
        if (docs != null) {
            schema.setExternalDocs(docs);
        }
    }
    Object example = getAnyExample("example", node, location, result);
    if (example != null) {
        schema.setExample(example instanceof NullNode ? null : example);
    }
    bool = getBoolean("deprecated", node, false, location, result);
    if (bool != null) {
        schema.setDeprecated(bool);
    }
    Map<String, Object> extensions = getExtensions(node);
    if (extensions != null && extensions.size() > 0) {
        schema.setExtensions(extensions);
    }
    Set<String> schemaKeys = getKeys(node);
    for (String key : schemaKeys) {
        if (!SCHEMA_KEYS.contains(key) && !key.startsWith("x-")) {
            result.extra(location, key, node.get(key));
        }
    }
    return schema;
}
Also used : DateSchema(io.swagger.v3.oas.models.media.DateSchema) ComposedSchema(io.swagger.v3.oas.models.media.ComposedSchema) DateTimeSchema(io.swagger.v3.oas.models.media.DateTimeSchema) ByteArraySchema(io.swagger.v3.oas.models.media.ByteArraySchema) ObjectSchema(io.swagger.v3.oas.models.media.ObjectSchema) ArraySchema(io.swagger.v3.oas.models.media.ArraySchema) Schema(io.swagger.v3.oas.models.media.Schema) MapSchema(io.swagger.v3.oas.models.media.MapSchema) JsonNode(com.fasterxml.jackson.databind.JsonNode) ByteArraySchema(io.swagger.v3.oas.models.media.ByteArraySchema) ArraySchema(io.swagger.v3.oas.models.media.ArraySchema) ExternalDocumentation(io.swagger.v3.oas.models.ExternalDocumentation) ObjectSchema(io.swagger.v3.oas.models.media.ObjectSchema) MapSchema(io.swagger.v3.oas.models.media.MapSchema) ArrayNode(com.fasterxml.jackson.databind.node.ArrayNode) ComposedSchema(io.swagger.v3.oas.models.media.ComposedSchema) SwaggerParseResult(io.swagger.v3.parser.core.models.SwaggerParseResult) ObjectNode(com.fasterxml.jackson.databind.node.ObjectNode) URISyntaxException(java.net.URISyntaxException) ParseException(java.text.ParseException) BigDecimal(java.math.BigDecimal) XML(io.swagger.v3.oas.models.media.XML) ParseException(java.text.ParseException) NullNode(com.fasterxml.jackson.databind.node.NullNode)

Example 9 with ResolverCache

use of io.swagger.v3.parser.ResolverCache in project swagger-parser by swagger-api.

the class ExternalRefProcessorTest method testRelativeRefIncludingUrlRef.

@Test
public void testRelativeRefIncludingUrlRef(@Injectable final Schema mockedModel) throws Exception {
    final RefFormat refFormat = RefFormat.RELATIVE;
    final String url = "https://my.example.remote.url.com/globals.yaml";
    final String expectedResult = "components:\n" + "  schemas:\n" + "    link-object:\n" + "      type: object\n" + "      additionalProperties:\n" + "        \"$ref\": \"#/components/schemas/rel-data\"\n" + "    rel-data:\n" + "      type: object\n" + "      required:\n" + "      - href\n" + "      properties:\n" + "        href:\n" + "          type: string\n" + "        note:\n" + "          type: string\n" + "    result:\n" + "      type: object\n" + "      properties:\n" + "        name:\n" + "          type: string\n" + "        _links:\n" + "          \"$ref\": \"#/components/schemas/link-object\"\n" + "";
    List<AuthorizationValue> auths = null;
    new Expectations() {

        {
            RemoteUrl.urlToString(url, auths);
            times = 1;
            result = expectedResult;
        }
    };
    OpenAPI mockedOpenAPI = new OpenAPI();
    mockedOpenAPI.setComponents(new Components());
    mockedOpenAPI.getComponents().setSchemas(new HashMap<>());
    ResolverCache mockedResolverCache = new ResolverCache(mockedOpenAPI, null, null);
    ExternalRefProcessor processor = new ExternalRefProcessor(mockedResolverCache, mockedOpenAPI);
    processor.processRefToExternalSchema("./relative-with-url/relative-with-url.yaml#/relative-with-url", refFormat);
    assertThat(((Schema) mockedOpenAPI.getComponents().getSchemas().get("relative-with-url").getProperties().get("Foo")).get$ref(), is("https://my.example.remote.url.com/globals.yaml#/components/schemas/link-object"));
    assertThat(mockedOpenAPI.getComponents().getSchemas().keySet().contains("link-object"), is(true));
    assertThat(mockedOpenAPI.getComponents().getSchemas().keySet().contains("rel-data"), is(true));
    // assert that ref is relative ref is resolved. and the file path is from root yaml file.
    assertThat(((Schema) mockedOpenAPI.getComponents().getSchemas().get("relative-with-url").getProperties().get("Bar")).get$ref(), is("./relative-with-url/relative-with-local.yaml#/relative-same-file"));
}
Also used : Expectations(mockit.Expectations) StrictExpectations(mockit.StrictExpectations) Components(io.swagger.v3.oas.models.Components) AuthorizationValue(io.swagger.v3.parser.core.models.AuthorizationValue) RefFormat(io.swagger.v3.parser.models.RefFormat) ResolverCache(io.swagger.v3.parser.ResolverCache) OpenAPI(io.swagger.v3.oas.models.OpenAPI) Test(org.testng.annotations.Test)

Example 10 with ResolverCache

use of io.swagger.v3.parser.ResolverCache in project swagger-parser by swagger-api.

the class ComponentsProcessorTest method testDefinitionsProcessor_RefModelInDefinitionsMap.

@Test
public void testDefinitionsProcessor_RefModelInDefinitionsMap(@Injectable final Schema resolvedModel) throws Exception {
    final OpenAPI openAPI = new OpenAPI();
    final String ref = "http://my.company.com/path/to/file.json#/foo/bar";
    final Schema refModel = new Schema().$ref(ref);
    openAPI.components(new Components().addSchemas("foo", refModel));
    final MockUp<ResolverCache> mockup = new MockUp<ResolverCache>() {

        @Mock
        String getRenamedRef(String ref) {
            openAPI.getComponents().getSchemas().put("bar", resolvedModel);
            return "bar";
        }
    };
    final ResolverCache mockResolverCache = mockup.getMockInstance();
    new StrictExpectations() {

        {
            new SchemaProcessor(mockResolverCache, openAPI);
            times = 1;
            result = schemaProcessor;
            new ResponseProcessor(mockResolverCache, openAPI);
            times = 1;
            result = responseProcessor;
            new RequestBodyProcessor(mockResolverCache, openAPI);
            times = 1;
            result = requestBodyProcessor;
            new ParameterProcessor(mockResolverCache, openAPI);
            times = 1;
            result = parameterProcessor;
            new HeaderProcessor(mockResolverCache, openAPI);
            times = 1;
            result = headerProcessor;
            new ExampleProcessor(mockResolverCache, openAPI);
            times = 1;
            result = exampleProcessor;
            new LinkProcessor(mockResolverCache, openAPI);
            times = 1;
            result = linkProcessor;
            new CallbackProcessor(mockResolverCache, openAPI);
            times = 1;
            result = callbackProcessor;
            new SecuritySchemeProcessor(mockResolverCache, openAPI);
            times = 1;
            result = securitySchemeProcessor;
            schemaProcessor.processSchema(refModel);
            times = 1;
            resolvedModel.getProperties();
            times = 1;
        }
    };
    new ComponentsProcessor(openAPI, mockResolverCache).processComponents();
    new FullVerifications() {

        {
        }
    };
    final Map<String, Schema> definitions = openAPI.getComponents().getSchemas();
    assertEquals(definitions.size(), 1);
    final Schema foo = definitions.get("foo");
    assertEquals(foo, resolvedModel);
}
Also used : Schema(io.swagger.v3.oas.models.media.Schema) Components(io.swagger.v3.oas.models.Components) ResolverCache(io.swagger.v3.parser.ResolverCache) OpenAPI(io.swagger.v3.oas.models.OpenAPI) Test(org.testng.annotations.Test)

Aggregations

Test (org.testng.annotations.Test)15 ResolverCache (io.swagger.v3.parser.ResolverCache)14 Components (io.swagger.v3.oas.models.Components)10 OpenAPI (io.swagger.v3.oas.models.OpenAPI)10 Schema (io.swagger.v3.oas.models.media.Schema)7 RefFormat (io.swagger.v3.parser.models.RefFormat)5 Expectations (mockit.Expectations)5 ApiResponse (io.swagger.v3.oas.models.responses.ApiResponse)3 ObjectMapper (com.fasterxml.jackson.databind.ObjectMapper)2 Parameter (io.swagger.v3.oas.models.parameters.Parameter)2 ParseOptions (io.swagger.v3.parser.core.models.ParseOptions)2 JsonNode (com.fasterxml.jackson.databind.JsonNode)1 ArrayNode (com.fasterxml.jackson.databind.node.ArrayNode)1 NullNode (com.fasterxml.jackson.databind.node.NullNode)1 ObjectNode (com.fasterxml.jackson.databind.node.ObjectNode)1 ExternalDocumentation (io.swagger.v3.oas.models.ExternalDocumentation)1 PathItem (io.swagger.v3.oas.models.PathItem)1 ArraySchema (io.swagger.v3.oas.models.media.ArraySchema)1 ByteArraySchema (io.swagger.v3.oas.models.media.ByteArraySchema)1 ComposedSchema (io.swagger.v3.oas.models.media.ComposedSchema)1