Skip to content

[BUG] Fix Swagger Parser doesn't handle $refs correctly when they are relatives without '../' #1948

Description

@jorgerod

Possible regression of this PR

I have defined an api contract as follows:

├── openapi.yaml
├── product
    ├── product-api.yaml
    ├── product-components.yaml

openapi.yaml

openapi: 3.0.0
info:
  title: Demo
  description: Demo to crash parser
  version: 1.0.0
paths:
  /findById/{param1}:
    $ref: 'product/product-api.yaml#/paths/findById~1{param1}' 

product-api.yaml

paths:
  findById/{param1}:
    get:
      summary: Gets service health status
      parameters:
#        - $ref: '../product/product-components.yaml#/components/parameters/param1' #OK
        - $ref: 'product-components.yaml#/components/parameters/param1' #KO
      responses:
        '200':
          description: Success status
          content:
            application/json:
              schema:
                $ref: 'product-components.yaml#/components/schemas/responseBase' #OK

product-components.yaml

components:
  schemas:
    responseBase:
      type: object
      properties:
        status:
          type: string 
  parameters:
    param1:
      in: path
      name: param1
      schema:
        type: string
        maxLength: 2147483647
      description: Unique identifier

When parameters are referenced in this way, they fail (they take the current directory as root):

- $ref: 'product-components.yaml#/components/parameters/param1' 

Trace:

java.lang.RuntimeException: Unable to load RELATIVE ref: product-components.yaml path: swagger-parser/modules/swagger-parser-v3/src/test/resources/issue
	at io.swagger.v3.parser.util.RefUtils.readExternalRef(RefUtils.java:220)
	at io.swagger.v3.parser.ResolverCache.loadRef(ResolverCache.java:150)
	at io.swagger.v3.parser.processors.ExternalRefProcessor.processRefToExternalParameter(ExternalRefProcessor.java:755)
	at io.swagger.v3.parser.processors.ParameterProcessor.processParameter(ParameterProcessor.java:46)
	at io.swagger.v3.parser.processors.OperationProcessor.processOperation(OperationProcessor.java:43)
	at io.swagger.v3.parser.processors.PathsProcessor.processPaths(PathsProcessor.java:88)
	at io.swagger.v3.parser.OpenAPIResolver.resolve(OpenAPIResolver.java:72)
	at io.swagger.v3.parser.OpenAPIResolver.resolve(OpenAPIResolver.java:59)
	at io.swagger.v3.parser.OpenAPIV3Parser.resolve(OpenAPIV3Parser.java:238)
	at io.swagger.v3.parser.OpenAPIV3Parser.readContents(OpenAPIV3Parser.java:181)
	at io.swagger.v3.parser.OpenAPIV3Parser.readLocation(OpenAPIV3Parser.java:97)
	at io.swagger.v3.parser.test.OpenAPIV3ParserTest.testIssueJRM(OpenAPIV3ParserTest.java:452)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
	at mockit.integration.junit4.JUnit4TestRunnerDecorator.executeTestMethod(JUnit4TestRunnerDecorator.java:157)
	at mockit.integration.junit4.JUnit4TestRunnerDecorator.invokeExplosively(JUnit4TestRunnerDecorator.java:71)
	at mockit.integration.junit4.FakeFrameworkMethod.invokeExplosively(FakeFrameworkMethod.java:29)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
	at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
	at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
	at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
	at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:232)
	at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:55)
Caused by: java.lang.RuntimeException: Could not find product-components.yaml on the classpath
	at io.swagger.v3.parser.util.ClasspathHelper.loadFileFromClasspath(ClasspathHelper.java:33)
	at io.swagger.v3.parser.util.RefUtils.readExternalRef(RefUtils.java:214)
	... 42 more

When they are referenced like this they go fine:

- $ref: '../product/product-components.yaml#/components/parameters/param1'

Prior to swagger-parser 2.0.31, the resolution of these references was correct (probably the bug is here:)

NOTE: Schemas from responses or request body work correctly in both cases.

my_openapi.zip

Related issues:

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions