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

ReDoc fails to expand JSON Schema refs in examples and x-examples when split among multiple files. Race condition? #311

Closed
brocoli opened this issue Jul 27, 2017 · 5 comments

Comments

@brocoli
Copy link

brocoli commented Jul 27, 2017

Ok, so this is a weird one.

I'm working on a decently sized API that uses $refs to other files in the same server very liberally. As soon as I started nesting the $refs I was using to document response examples and body parameter x-examples, and they started increasing in size, ReDoc started printing things like this in the sidebar example boxes:

{
  "config": {
    "$ref": "#/paths/~1%7Bobjective_id%7D~1config/put/parameters/5/x-examples/application~1json"
  },
  "state": {
    "$ref": "#/paths/~1%7Bobjective_id%7D~1state~1actions~1contribute/post/parameters/4/x-examples/application~1json"
  }
}

This in particular is the response 200 example for a GET in the endpoint /{objective_id}, so it's very strange that there are references to i.e. parameters/5/x-examples in the strings in there (GET can't even have a working x-examples because those only work with body parameters...). Those parameters do exist in other endpoints though.

Also, for the record, this is the definition of the response 200 for this endpoint:

      responses:
        200:
          description: >
            Success response returning an existing objective's data.
          schema:
            $ref: "#/definitions/response_200_objective_id"
          examples:
            application/json:
              $ref: "./examples/objective_id.json"

And inside examples/objective_id.json:

{
  "config": {
    "$ref": "./objective_id_config.json"
  },
  "state": {
    "$ref": "./objective_id_state.json"
  }
}

Or rather, it's the above JSON, but minified. objective_id_state.json does not have any $refs, but objective_id_config.json has multiple $refs inside it. No $ref chain is ever circular.

The examples were originally in YAML, but I found out that converting them to JSON and minifying them caused the final ReDoc to expand more examples correctly. Similarly, removing all x-examples causes the final ReDoc to expand more of the remaining examples correctly (but not all), and the converse, removing examples to make it expand more x-examples correctly also works. The same happens by trying to "flatten out" the examples structure into fewer files.

It's also not a problem with the JSONs themselves, since other endpoints down the line in the specification also access these files expand them correctly (yes, the exact same example is not expanded in one path definition but then is correctly expanded in the next).

I believe there's some sort of strange race condition going on here, where ReDoc is not waiting for the whole final JSON spec to be loaded correctly before rendering, so it's rendering garbage. Either that or it's a similar bug in the YAML / JSON parser.

Also to note, my definitions are also behind a $ref, and there are no problems with the rendering of them.

This all happened with me running a local server with python -m http.server, in Google Chrome, in a macOS.

Versions:
Chrome: Version 58.0.3029.110 (64-bit)
macOS: 10.12.5
python: 3.6.1

@RomanHotsiy
Copy link
Member

@brocoli thanks for detailed issue report.
I will get back once I find time to check this issue

@RomanHotsiy
Copy link
Member

@brocoli could you please setup minimal reproducible example e.g. in a form of GitHub repo or gist with multiple files.

@c0dingn0mad
Copy link

Hi,

I had a similar problem, so I dug into json-schema-ref-parser because I couldn't find any bug in ReDoc.

It turns out ReDoc uses the method "bundle" which in resolves all external refs but leaves internal refs in tact. The idea is to keep the resulting json file relatively small.

I changed the method call in the spec-manager's load method to "dereference" and that solved the issue for me.

this.parser.dereference(urlOrObject, {http: {withCredentials: false}})
instead of
this.parser.bundle(urlOrObject, {http: {withCredentials: false}})

I am not too familiar with the ReDoc code so I am not sure if this should happen elsewhere, but as far as I can tell, this is the only place where json-schema-ref-parser is being used.

Regards,
Mirko

patch.diff

@RomanHotsiy
Copy link
Member

Could you please verify this issue with [email protected]?

@RomanHotsiy
Copy link
Member

Closing as housekeeping.
Feel free to reopen

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

No branches or pull requests

3 participants