APIDevTools / swagger-parser

Swagger 2.0 and OpenAPI 3.0 parser/validator
https://apitools.dev/swagger-parser
MIT License
1.08k stars 153 forks source link

Error resolving circular references #208

Open jdegre opened 2 years ago

jdegre commented 2 years ago

Hi, I have found an error in the resolver in latest versions 10.0.x of swagger-parser (it was working fine in versions 9.0.x). The error occurs while de-referencing circular references in APIs with external references across different files.

Let me include an example of cross-referenced APIs, to reproduce the error:

Main file openapi.yaml:

openapi: 3.0.0
info:
  title: Main
  version: 1.0.0
paths: {}
components:
  schemas:
    MainType:
      anyOf:
        - $ref: 'A.yaml#/components/schemas/A4'
        - $ref: 'A.yaml#/components/schemas/A1'

File A.yaml:

openapi: 3.0.0
info:
  title: A
  version: 1.0.0
paths: {}
components:
  schemas:
    A1:
      type: object
      properties:
        data1:
          $ref: '#/components/schemas/A2'
    A2:
      type: array
      items:
        $ref: '#/components/schemas/A3'
    A3:
      type: object
      properties:
        data3:
          $ref: '#/components/schemas/A2'
    A4:
      anyOf:
        - $ref: '#/components/schemas/A3'
        - $ref: '#/components/schemas/A1'

If you try to validate the main API with swagger-parser 10.0.x, using e.g.:

SwaggerParser.validate('./openapi.yaml');

you get the error:

Token "A1" does not exist.

In earlier versions (9.x.0) it worked fine (as it should, since A1 is obviously resolvable).

For what is worth, and if it helps to troubleshoot the issue, I noted that in the main file openapi.yaml, the order of the items in the anyOf construct, seems to matter. So, if you have:

      anyOf:
        - $ref: 'A.yaml#/components/schemas/A4'
        - $ref: 'A.yaml#/components/schemas/A1'

it fails the resolution. While, if you have:

      anyOf:
        - $ref: 'A.yaml#/components/schemas/A1'
        - $ref: 'A.yaml#/components/schemas/A4'

it works fine (in versions 10.x.0 too!)

jdegre commented 2 years ago

Hi again, The example above is a narrowed-down excerpt, that comes form a real-life API, but I guess it looks like a non-realistic and convoluted example, having such artificial data type names, and weird type relationships... :)

Let me add another example, even simpler, and with quite realistic data type names and references, so I hope it makes it quite apparent that the failure can indeed occur VERY frequently:

File openapi.yaml:

openapi: 3.0.0
info:
  title: Main
  version: 1.0.0
paths: {}
components:
  schemas:
    Family:
      type: object
      properties:
        father:
          $ref: 'A.yaml#/components/schemas/Person'
        mother:
          $ref: 'A.yaml#/components/schemas/Person'
        friends:
          $ref: 'A.yaml#/components/schemas/ListOfPersons'

File A.yaml:

openapi: 3.0.0
info:
  title: A
  version: 1.0.0
paths: {}
components:
  schemas:
    Person:
      type: object
      required: [ id ] 
      properties:
        id:
          type: string
        children:
          $ref: '#/components/schemas/ListOfPersons'

    ListOfPersons:
      type: array
      items:
        $ref: '#/components/schemas/Person'

When the validation of openapi.yaml is done with swagger-parser 10.0.x, it gives this error:

Token "ListOfPersons" does not exist.

With swagger-parser 9.0.x, it validates successfully.

Cheers, /jdegre.