swagger-api / swagger-parser

Swagger Spec to Java POJOs
http://swagger.io
Apache License 2.0
777 stars 525 forks source link

ResolveFully fails on internal references when the initial spec is read from a file URL #1922

Open klease opened 1 year ago

klease commented 1 year ago

Hi, While testing the new 3.1.0 feature of a pathItem in components, I found that resolveFully is not replacing internal references such as $ref: "#/components/pathItems/getPet" when the initial URL to the spec is a file:// URL. There is an exception in the log like this:

java.io.FileNotFoundException: file:/...../target/test-classes/petstore-3.1.yaml (Aucun fichier ou dossier de ce type)
        at java.io.FileInputStream.open0(Native Method) ~[?:?]
        at java.io.FileInputStream.open(FileInputStream.java:216) ~[?:?]
        at java.io.FileInputStream.<init>(FileInputStream.java:157) ~[?:?]
        at java.io.FileInputStream.<init>(FileInputStream.java:111) ~[?:?]
        at io.swagger.v3.parser.reference.Visitor.readFile(Visitor.java:66) ~[swagger-parser-v3-2.1.13.jar:2.1.13]
        at io.swagger.v3.parser.reference.Visitor.readURI(Visitor.java:84) ~[swagger-parser-v3-2.1.13.jar:2.1.13]
        at io.swagger.v3.parser.reference.ReferenceVisitor.parse(ReferenceVisitor.java:279) ~[swagger-parser-v3-2.1.13.jar:2.1.13]

This is true for any internal reference from the initial specification. The Visitor.readFile() method needs to transform the file URL to a valid path. I've never contributed to swagger before but I could create a test case and PR for this issue.

jpommerening commented 1 month ago

Yup, same here, Swagger Parser 2.1.22. I have a very basic OpenAPI 3.1 file without any external references and when I use options.setResolve(), the FileNotFoundException is logged and SwaggerParseResult contains the caught exception message.

Interestingly the issue only happens with OpenAPI 3.1 (not with OpenAPI 3.0, or Swagger 2.0).

Here's some more of the stack trace:

java.io.FileNotFoundException: file:/.../test-3.1.openapi.json (No such file or directory)
    at java.base/java.io.FileInputStream.open0(Native Method)
    at java.base/java.io.FileInputStream.open(FileInputStream.java:219)
    at java.base/java.io.FileInputStream.<init>(FileInputStream.java:157)
    at java.base/java.io.FileInputStream.<init>(FileInputStream.java:112)
    at io.swagger.v3.parser.reference.Visitor.readFile(Visitor.java:66)
    at io.swagger.v3.parser.reference.Visitor.readURI(Visitor.java:84)
    at io.swagger.v3.parser.reference.ReferenceVisitor.parse(ReferenceVisitor.java:305)
    at io.swagger.v3.parser.reference.ReferenceVisitor.resolveSchemaRef(ReferenceVisitor.java:241)
    at io.swagger.v3.parser.reference.ReferenceVisitor.visitSchema(ReferenceVisitor.java:141)

Should Visitor.readURI() maybe strip the file: prefix before calling Visitor.readFile() or use File(URI) rather than File(String)?

edit

Workaround: strip the file: scheme from the URI before passing it to parseLocation(). Instead of using getResource( "x" ).toURI(), you can use URI.create( getResource( "x" ).toString().replaceFirst( "^file:", "" )