cebe / php-openapi

Read and write OpenAPI yaml/json files and make the content accessible in PHP objects.
MIT License
466 stars 88 forks source link

References fail to resolve in directory structure #32

Closed jasonbstanding closed 4 years ago

jasonbstanding commented 5 years ago

This may be a replica of issue #13 , but I thought I'd report it - I'm using php-openapi by way of the lezhnev openapi/psr7-validator, and am coming up against the following:

I have a file structure like this:

open-api.yaml
Paths
 - pathdef1.yaml
 - pathdef2.yaml
Requests
 - requestschema1.yaml
 - requestschema2.yaml
Responses
 - responseschema1.yaml
 - responseschema2.yaml

open-api.yaml contains the "components" collection, and inside that, "schemas". Schemas contains a list of keys, each with a $ref variable pointed at an external file.

components:
   schemas:
      Request.1:
         $ref: "Requests/requestschema1.yaml"
      Request.2:
         $ref: "Requests/requestschema2.yaml"
      Response.1:
         $ref: "Responses/responseschema1.yaml"
      Response.2:
         $ref: "Responses/responseschema2.yaml"

Sometimes cases come up where a Response schema contains objects defined in another response schema:

title: "Response 2 object"
description: "A response containing some Response 1 objects"
type: "object"
properties:
    id:
        type: "integer"
        format: "int32"
    payload:
        $ref: "../open-api.yaml#/components/schemas/Response.1"

Additionally, the open-api.yaml file contains the path declarations. Each is defined in an external file (as above), and inside those files if any schemas are needed, they're referenced as keys in the open-api.yaml#/components/schemas collection, rather than directly to files.

The chief problems I'm getting are: 1) From stepping through the code, I think that every time the open-api.yaml file refers to an external file that file has to be loaded, and then every time that file references open-api.yaml the parent file is reloaded again. If running with XDebug active this times out and isn't able to complete to help me understand where/why the second bug is taking place.

2) If left to run without debug, at some point the file referencing fails and one of the external files seems to lose track of where in the file structure to look for the next link - one fo the objects is resolving a $ref to "file:///var/www/html/public/api-doc/../open-api.yaml" instead of "file:///var/www/html/public/api-doc/open-api.yaml", but with a timing out debug process I can't see where. The "root" file path is file:///var/www/html/public/api-doc/open-api.yaml, so any $ref'd files inside that file would be file:///var/www/html/public/api-doc/Responses/{filename} or file:///var/www/html/public/api-doc/Requests/{filename} or file:///var/www/html/public/api-doc/Paths/{filename} - but if those external files contain a link back, they're referencing "../open-api.yaml#/components/schemas/{etc}".

My questions are:

The OAS document I have validates using wework/speccy 11.0 and swagger-cli, and opens in redoc - so I'm reasonably confident between the 3 of those it's syntactically correct...

Happy to provide more detail offline if it helps.

cebe commented 5 years ago

Thanks for the detailed report!

* would caching (the way you're thinking about implementing it) solve the repeated reloading of the "base" open-api.yaml file?

yes, that should solve the problem of reloading the file. Every file should only be loaded once in a ReferenceContext and next time should be accessed directly from memory.

if open-api.yaml were able to be parsed as some kind of dictionary, would that likely address the problem of objects containing $refs which contain objects which contain $refs losing track of what level of the filesystem they represent?

With the current implementation of ReferenceContext there should not be a situation where an object looses track of where it is located. I suspect a bug there, need to debug this.

cebe commented 4 years ago

got a fix in #39, please check it out and let me know if this solves the problem.