Skip to content
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

Passing "resolveInternal" option causes "RangeError" when resolving a spec #420

Open
mihirkothari25 opened this issue Jun 12, 2020 · 6 comments

Comments

@mihirkothari25
Copy link

Detailed description

This might be a bug with oas-resolver but the front-door we are using to resolve the OpenApi specs is speccy.
Resolving refs works fine with the following options

const SPECCY_OPTIONS = {
  resolve: true,
  jsonSchema: true,
}

The above options cause the first external ref to be resolved, but subsequent external refs to that same file get converted to internal refs.

We have a use case where we need all the refs to be resolved and not have any internal refs, so I used the following options

const SPECCY_OPTIONS = {
  resolve: true,
  jsonSchema: true,
  resolveInternal: true,
}

This causes the following error -

RangeError: Maximum call stack size exceeded
at String.replace (<anonymous>)
at jpescape (/Users/mkothari/git/platform-specs/node_modules/reftools/lib/jptr.js:9:14)
at recurse (/Users/mkothari/git/platform-specs/node_modules/reftools/lib/recurse.js:34:60)
at recurse (/Users/mkothari/git/platform-specs/node_modules/reftools/lib/recurse.js:53:13)
at recurse (/Users/mkothari/git/platform-specs/node_modules/reftools/lib/recurse.js:53:13)
at recurse (/Users/mkothari/git/platform-specs/node_modules/reftools/lib/recurse.js:53:13)
at recurse (/Users/mkothari/git/platform-specs/node_modules/reftools/lib/recurse.js:53:13)
at recurse (/Users/mkothari/git/platform-specs/node_modules/reftools/lib/recurse.js:53:13)
at recurse (/Users/mkothari/git/platform-specs/node_modules/reftools/lib/recurse.js:53:13)
at recurse (/Users/mkothari/git/platform-specs/node_modules/reftools/lib/recurse.js:53:13)
  • Node Version: 12.18.0
  • Operating system and version (e.g. Ubuntu 16.04, Windows 7): Mac 10.15.5
  • Speccy Version: 0.11.0
@mihirkothari25
Copy link
Author

An additional note - this the schema does have recursion and is structured as given in the example from the json-schema docs - https://json-schema.org/understanding-json-schema/structuring.html#recursion

@mihirkothari25
Copy link
Author

A quick example test case -
the yaml spec, say temp.yaml -

openapi: 3.0.2
info:
  title: api
  description: |
    description!
  contact:
    name: 'team'
    url: 'https://test.com/'
    email: 'test@test.com'
  version: 0.0.1
servers:
  - url: https://test.com
paths: {}
components:
  responses:
    Request:
      description: request
      content:
        application/json:
          schema:
            $ref: temp.json#/definitions/person
tags: []

the schema in a file temp.json

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "definitions": {
    "person": {
      "type": "object",
      "properties": {
        "name": { "type": "string" },
        "children": {
          "type": "array",
          "items": { "$ref": "#/definitions/person" },
          "default": []
        }
      }
    }
  },
  "type": "object",
  "properties": {
    "person": { "$ref": "#/definitions/person" }
  }
}

The command to run is - speccy resolve ./temp.yaml -j -v -i
Error -

GET ./packages/common-spec/src/specifications/components/temp.yaml
GET /Users/mkothari/git/common-specs/packages/common-spec/src/specifications/components/temp.json #/definitions/person
RangeError: Maximum call stack size exceeded
    at String.replace (<anonymous>)
    at jpescape (/Users/mkothari/git/common-specs/node_modules/reftools/lib/jptr.js:9:14)
    at recurse (/Users/mkothari/git/common-specs/node_modules/reftools/lib/recurse.js:34:60)
    at recurse (/Users/mkothari/git/common-specs/node_modules/reftools/lib/recurse.js:53:13)
    at recurse (/Users/mkothari/git/common-specs/node_modules/reftools/lib/recurse.js:53:13)
    at recurse (/Users/mkothari/git/common-specs/node_modules/reftools/lib/recurse.js:53:13)
    at recurse (/Users/mkothari/git/common-specs/node_modules/reftools/lib/recurse.js:53:13)
    at recurse (/Users/mkothari/git/common-specs/node_modules/reftools/lib/recurse.js:53:13)
    at recurse (/Users/mkothari/git/common-specs/node_modules/reftools/lib/recurse.js:53:13)
    at recurse (/Users/mkothari/git/common-specs/node_modules/reftools/lib/recurse.js:53:13)
Maximum call stack size exceeded

@MikeRalphson
Copy link
Contributor

What is your expected (non infinite) output if all internal references are to be replaced?

@mihirkothari25
Copy link
Author

That's a good question. IMO resolving it to the top level would suffice with a reference back to the object itself further down the tree.

This would be the desired output -

openapi: 3.0.2
info:
  title: api
  description: |
    description!
  contact:
    name: team
    url: https://test.com/
    email: test@test.com
  version: 0.0.1
servers:
  - url: https://test.com
paths: {}
components:
  responses:
    Request:
      description: request
      content:
        application/json:
          schema:
            type: object
            properties:
              name:
                type: string
              children:
                type: array
                items:
                  $ref: "#/components/responses/Request/content/application~1json/schema"
                default: []
tags: []

@MikeRalphson
Copy link
Contributor

That is exactly the output if you don't specifiy resolveInternal: true.

@mihirkothari25
Copy link
Author

I think I simplified my test yaml too much without showcasing the actual use case I am looking to solve.
If you refer to the same schema multiple times in the spec (which is what we are doing), as shown in the example below -

openapi: 3.0.2
info:
  title: api
  description: |
    description!
  contact:
    name: 'team'
    url: 'https://test.com/'
    email: 'test@test.com'
  version: 0.0.1
servers:
  - url: https://test.com
paths: {}
components:
  responses:
    Request:
      description: request
      content:
        application/json:
          schema:
            $ref: temp.json#/definitions/person
    Request2:
      description: request
      content:
        application/json:
          schema:
            $ref: temp.json#/definitions/person
tags: []

if I don't specify resolveInternal: true then it results in this -

openapi: 3.0.2
info:
  title: api
  description: |
    description!
  contact:
    name: team
    url: https://test.com/
    email: test@test.com
  version: 0.0.1
servers:
  - url: https://test.com
paths: {}
components:
  responses:
    Request:
      description: request
      content:
        application/json:
          schema:
            type: object
            properties:
              name:
                type: string
              children:
                type: array
                items:
                  type: object
                  properties:
                    name:
                      type: string
                    children:
                      type: array
                      items:
                        $ref: "#/components/responses/Request/content/application~1json/schema/properti\
                          es/children/items"
                      default: []
                default: []
    Request2:
      description: request
      content:
        application/json:
          schema:
            $ref: "#/components/responses/Request/content/application~1json/schema"
tags: []

It resolves it the first time, and then any future references point to the first place it was resolved.

Our goal was to have it resolve in all spots, which is why we added resovleInternal: true, which then resulted in the RangeError.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants