swagger-js icon indicating copy to clipboard operation
swagger-js copied to clipboard

[Bug] Caching $ref issue with multiple files

Open hwo411 opened this issue 7 years ago • 1 comments

The same pointers in different files cause mutations not being applied. The problem is in these lines of code: https://github.com/swagger-api/swagger-js/blob/master/src/specmap/index.js#L114-L130

obj.$$ref doesn't include file info and the same pointers in different files are treated as the same one.

One of the results - allOf isn't expanded and swagger-ui does't display sub-items. (see response on the screenshot) As a quick and dirty workaround for those who are affected: either cache can be disabled or allOf can be expanded in swagger-ui.

The problem is that there is no info from which file the pointer comes inside the traverse function, so such info should be passed there in some way to make the pointer unique and avoid false cache hits. I'm not so familiar with the code, so I can't select the proper way to pass such info, I see a few options:

  • $$ref should always contain file, which doesn't seem a correct way to me
  • mutation should always have additional parameter with file info
  • context has to be passed in some way

With the decision I can prepare the fix and the tests.

Screenshot: image

The simplified example from a real case(which has more than 1 element in allOf and oneOf):

requests.yml

components:
  schemas:
    Object:
      title: Request
      type: object
      required:
        - param
      properties:
        param:
          $ref: "#/components/schemas/Param"
      example:
        param:
          name: qqq
          number: 3

    Param:
      oneOf:
        - $ref: "#/components/schemas/SubParam"

    SubParam:
      allOf:
      - properties:
          name:
            type: string
            example: qqq
      - properties:
          number:
            type: integer
            example: 3

responses.yml

components:
  schemas:
    Object:
      title: Response
      type: object
      required:
        - param
      properties:
        param:
          $ref: "#/components/schemas/Param"
      example:
        param:
          slug: zzz
          id: 1

    Param:
      oneOf:
        - $ref: "#/components/schemas/SubParam"

    SubParam:
      allOf:
        - properties:
            slug:
              type: string
              example: zzz
        - properties:
            id:
              type: integer
              example: 3

api.yml

openapi: "3.0.0"
paths:
  /broken:
    post:
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "requests.yml#/components/schemas/Object"
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                $ref: "responses.yml#/components/schemas/Object"

hwo411 avatar Mar 27 '18 14:03 hwo411

Yep, this is a bug.

We compute fully-qualified pointers elsewhere in the $ref plugin; using those here would probably solve this.

shockey avatar Mar 27 '18 18:03 shockey