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

Error resolving $refs to files in same directory #93

Closed
philosowaffle opened this issue Jul 28, 2018 · 8 comments
Closed

Error resolving $refs to files in same directory #93

philosowaffle opened this issue Jul 28, 2018 · 8 comments

Comments

@philosowaffle
Copy link

Windows
node v10.7.0
json-schema-ref-parser v5.1.1

petstore.yaml -- root, see full file structure here

swagger: "2.0"
info:
  version: 1.0.0
  title: Swagger Petstore
  license:
    name: MIT
host: petstore.swagger.io
basePath: /v1
schemes:
  - http
consumes:
  - application/json
produces:
  - application/json
paths:
  /pets:
    $ref: 'pets.yaml'
  /pets/{petId}:
    $ref: 'pets_petId.yaml'
definitions:
  Pet:
    properties:
      id:
        type: integer
        format: int64
  Error:
    $ref: 'error.yaml'

code

const refParser = require('json-schema-ref-parser')

var rootOpenApiFile = `G:\code\git\vs-openapi-designer\test\resource\v2.0\yaml\issue_01\petstore.yaml`;
return refParser.bundle(rootOpenApiFile, {}, function (err, schema) {
        console.log(err);
        return Promise.reject(this.dictToString(err));
    });

error

ENOENT: no such file or directory, open 'G:\code\git\vs-openapi-designer\test\resource\v2.0\yaml\issue_01\petstore.yaml\pets.yaml'
	at ReadFileContext.callback (G:\Code\Git\vs-openapi-designer\node_modules\json-schema-ref-parser\lib\resolvers\file.js:52:20)
	at FSReqWrap.readFileAfterOpen [as oncomplete] (fs.js:359:13)

It appears the reference to pets.yaml is just getting appended after the fq path to the root file instead of to the directory containing the root file.

Any help appreciated.

@JamesMessinger
Copy link
Member

I'm unable to reproduce this issue. Here's my attempt to reproduce it:

https://runkit.com/bigstickcarpet/json-schema-ref-parser-issue-93

Notice the error message at the bottom. The path to pets.yaml is correct.

@JamesMessinger
Copy link
Member

I noticed that your original code was using a Windows path, so I also ran this test on a Windows machine, to make sure it wasn't a Windows-specific bug. However, it worked correctly on Windows too.

@philosowaffle
Copy link
Author

philosowaffle commented Jul 30, 2018

I've verified this on two different (windows) machines now. I suppose that means I am using the library incorrectly.

After stepping through more of the code I think I have narrowed down the exact scenario. Despite the error message, I actually believe it is this ref that is causing the problem.

The only thing unique about my setup is that this is all running within a VSCode extension. If I have time later I'll see if I can recreate this issues as a unit test against this project.

Edit: Just saw your test to try and reproduce, I think you need to add a ref similar to what I have linked above in this comment inside of pets.yaml.

@JamesMessinger
Copy link
Member

JamesMessinger commented Jul 31, 2018

Cool! I look forward to trying out your VSCode extension!

I cloned your repo locally on a Windows machine, then created a bug_reproduction.js file in the test\resources\v2.0\yaml folder. Here is the complete contents of bug_reproduction.js:

const refParser = require('json-schema-ref-parser')

refParser.bundle('petstore.yaml', (err, schema) => {
  if (err) {
    console.error('ERROR:', err);
  }
  else {
    console.log('SUCCESS:', schema);
  }
});

Then I ran the script like this:

cd test\resources\v2.0\yaml
node bug_reproduction.js

And it worked correctly. Can you please try the same script on your machine and see if it works. If you get an error, then perhaps there's something unique about your environment which is causing the problem. Perhaps some issue with file or folder permissions, or something?

@JamesMessinger
Copy link
Member

Oh wait! I may have just reproduced the error... or at least a similar error that may be related to yours.

In the example above, the script file (bug_reproduction.js), the schema file (petstore.yaml), and the CWD (test\resources\v2.0\yaml) were all in the same directory. But then I modified the script to use an absolute path instead of a relative path:

const refParser = require('json-schema-ref-parser');
const path = require('path');

let absolutePath = path.join(__dirname, 'petstore.yaml');

refParser.bundle(absolutePath, (err, schema) => {
  if (err) {
    console.error('ERROR:', err);
  }
  else {
    console.log('SUCCESS:', schema);
  }
});

And I ran the script from a different directory:

cd \
node bug_reproduction.js

And I got this error, which is similar to the one you got:

ERROR: {
  "name": "SyntaxError",
  "message": "Unable to resolve $ref pointer \"c:https:///vs-openapi-designer-develop/test/resource/v2.0/yaml/petstore.yaml\"",
  "stack": "SyntaxError: Unable to resolve $ref pointer \"c:https:///Users/James%20Messinger/Desktop/vs-openapi-designer/test/resource/v2.0/yaml/petstore.yaml\"    
    at onError (C:\\vs-openapi-designer\\test\\resource\\v2.0\\yaml\node_modules\\json-schema-ref-parser\\lib\\parse.js:83:20)
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:182:7)
    at Function.Module.runMain (internal/modules/cjs/loader.js:697:11)
    at startup (internal/bootstrap/node.js:201:19)
    at bootstrapNodeJSCore (internal/bootstrap/node.js:516:3)"
}

After a bit of debugging, I discovered that the error is caused by the getProtocol() function, which is incorrectly interpreting the Windows drive letter (e.g. C:\) as a URL protocol.

I will release a patch for this bug momentarily. Hopefully it fixes your issue. Please let me know either way.

JamesMessinger added a commit that referenced this issue Jul 31, 2018
@JamesMessinger
Copy link
Member

Just released the patched version (5.1.2). Give it a try and lemme know

@philosowaffle
Copy link
Author

First of all, thank you for taking some extra time to investigate further.

I installed the patch and copied your test and tried running via the command line (to avoid any potential vscode abnormalities) and I had the exact same error as before.

I'm not sure why you don't get the same error as me but I have been able to solve my issue.

I believe this boils down to me incorrectly using json refs/pointers in the schema. In the child schema pets.yaml I have outlined below the results of what I learned this morning:

source

get:
  summary: List all pets
  operationId: listPets
  tags:
    - pets
  parameters:
    - name: limits
      in: query
      description: How many items to return at one time (max 100)
      required: false
      type: integer
      format: int32
  responses:
    "200":
      description: A paged array of pets
      headers:
        x-next:
          type: string
          description: A link to the next page of responses
      schema:
        # $ref: '../petstore.yaml/#/definitions/Error' # this ref works, but I don't think it should, this is be referencing one directory up
        # $ref: './petstore.yaml/#/definitions/Error' # fails
        # $ref: 'petstore.yaml/#/definitions/Error' # fails
        # $ref: '../petstore.yaml#/definitions/Error' # works, but I don't think it should, this is be referencing one directory up
        # $ref: './petstore.yaml#/definitions/Error' # works
        $ref: 'petstore.yaml#/definitions/Error' # works

I was adding an additional / between the root file and the #, this appears to be the source of the issue. After fixing this, I was able to successfully build a bundled schema.

I am happy to close this issue if you are, though I do think it was a little odd you were not able to reproduce it on your machine. It's possible there's still an environment issue on my end. Thanks.

@JamesMessinger
Copy link
Member

ah, I see. So the problem was the / before the # character. That explains it. A trailing slash at the end of a URL causes it to be treated as a directory, not a file.

For example, if you're in https://example.com/foo/bar.yaml, then here's how the following references will be resolved:

$ref: other.yaml      # will resolve to https://example.com/foo/other.yaml
$ref: ./other.yaml    # will resolve to https://example.com/foo/other.yaml
$ref: ../other.yaml   # will resolve to https://example.com/other.yaml

But if you're in https://example.com/foo/bar.yaml/ (notice the trailing slash, which indicates that bar.yaml is a directory, not a file), then here's how those references will be resolved:

$ref: other.yaml      # will resolve to https://example.com/foo/bar.yaml/other.yaml
$ref: ./other.yaml    # will resolve to https://example.com/foo/bar.yaml/other.yaml
$ref: ../other.yaml   # will resolve to https://example.com/foo/other.yaml

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

2 participants