Skip to content

Commit

Permalink
feat: resolver add ignoreIOErrors option, refs #282
Browse files Browse the repository at this point in the history
  • Loading branch information
MikeRalphson committed Sep 18, 2020
1 parent d93bd30 commit e142702
Show file tree
Hide file tree
Showing 6 changed files with 195 additions and 11 deletions.
1 change: 1 addition & 0 deletions docs/options.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ fetch|function|Input|Used to override the internal `fetch` implementation
fetchOptions|Object|Input|Additional options to be passed to `fetch` calls
handlers|Object|Input|Map of additional [protocol/scheme handlers](handlers.md), must be functions which return a Promise
help|Boolean|Reserved|Command-line flag to display help
ignoreIOErrors|Boolean|Input|Set to `true` to ignore IO errors when resolving
indent|String|Input|Command-line flag to control JSON indenting
isCallback|Boolean|Input|Hint to the linter that we are within a `callback` object
laxDefaults|Boolean|Input|Flag to validation step to ignore default/type mismatches
Expand Down
52 changes: 41 additions & 11 deletions packages/oas-resolver/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,21 @@ function unique(arr) {
return [... new Set(arr)];
}

function readFileAsync(filename, encoding) {
function readFileAsync(filename, encoding, options, pointer, def) {
return new Promise(function (resolve, reject) {
fs.readFile(filename, encoding, function (err, data) {
if (err)
reject(err);
else
if (err) {
if (options.ignoreIOErrors && def) {
options.externalRefs[pointer].failed = true;
resolve(def);
}
else {
reject(err);
}
}
else {
resolve(data);
}
});
});
}
Expand Down Expand Up @@ -82,13 +90,23 @@ function resolveAllFragment(obj, context, src, parentPath, base, options) {
let newRef = url.resolve(base,obj[key]).toString();
if (options.verbose>1) console.warn(common.colour.yellow+'Rewriting external url ref',obj[key],'as',newRef,common.colour.normal);
obj['x-miro'] = obj[key];
if (!options.externalRefs[newRef]) {
options.externalRefs[newRef] = options.externalRefs[obj[key]];
}
options.externalRefs[newRef].failed = options.externalRefs[obj[key]].failed;
obj[key] = newRef;
}
else if (!obj['x-miro']) {
let newRef = url.resolve(base,obj[key]).toString();
if (options.verbose>1) console.warn(common.colour.yellow+'Rewriting external ref',obj[key],'as',newRef,common.colour.normal);
obj['x-miro'] = obj[key]; // we use x-miro as a flag so we don't do this > once
obj[key] = newRef;
let failed = false;
if (options.externalRefs[obj[key]]) {
failed = options.externalRefs[obj[key]].failed;
}
if (!failed) {
if (options.verbose>1) console.warn(common.colour.yellow+'Rewriting external ref',obj[key],'as',newRef,common.colour.normal);
obj['x-miro'] = obj[key]; // we use x-miro as a flag so we don't do this > once
obj[key] = newRef;
}
}
}
});
Expand Down Expand Up @@ -187,7 +205,15 @@ function resolveExternal(root, pointer, options, callback) {
const fetchOptions = Object.assign({}, options.fetchOptions, { agent: options.agent });
return options.fetch(target, fetchOptions)
.then(function (res) {
if (res.status !== 200) throw new Error(`Received status code ${res.status}: ${target}`);
if (res.status !== 200) {
if (!options.ignoreIOErrors) {
throw new Error(`Received status code ${res.status}: ${target}`);
}
else {
options.externalRefs[pointer].failed = true;
return '{"$ref":"'+pointer+'"}';
}
}
return res.text();
})
.then(function (data) {
Expand Down Expand Up @@ -226,7 +252,8 @@ function resolveExternal(root, pointer, options, callback) {
});
}
else {
return readFileAsync(target, options.encoding || 'utf8')
const def = '{"$ref":"'+pointer+'"}';
return readFileAsync(target, options.encoding || 'utf8', options, pointer, def)
.then(function (data) {
try {
let context = yaml.parse(data, { schema:'core', prettyErrors: true });
Expand Down Expand Up @@ -291,8 +318,11 @@ function scanExternalRefs(options) {
refs[$ref] = { resolved: false, paths: [], extras:{}, description: obj[key].description };
}
if (refs[$ref].resolved) {
if (options.rewriteRefs) {
// we've already seen it
// we've already seen it
if (refs[$ref].failed) {
// do none
}
else if (options.rewriteRefs) {
let newRef = refs[$ref].resolvedAt;
if (options.verbose>1) console.warn('Rewriting ref', $ref, newRef);
obj[key]['x-miro'] = $ref;
Expand Down
59 changes: 59 additions & 0 deletions test/resolver/issue282/input.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
openapi: "3.0.0"
info:
version: 1.0.0
title: Swagger Petstore
license:
name: MIT
servers:
- url: http://petstore.swagger.io/v1
paths:
/pets:
get:
summary: List all pets
operationId: listPets
tags:
- pets
parameters:
- name: limit
in: query
description: How many items to return at one time (max 100)
required: false
schema:
type: integer
format: int32
responses:
'200':
description: An paged array of pets
headers:
x-next:
description: A link to the next page of responses
schema:
type: string
content:
application/json:
schema:
$ref: "pet.yaml"
post:
summary: Create pet
tags:
- pets
parameters:
- name: limit
in: query
description: How many items to return at one time (max 100)
required: false
schema:
type: integer
format: int32
responses:
'200':
description: An paged array of pets
content:
application/json:
schema:
$ref: "./pet.yaml"
'400':
content:
application/json:
schema:
$ref: "incorrect-ref.yaml"
1 change: 1 addition & 0 deletions test/resolver/issue282/options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ignoreIOErrors: true
81 changes: 81 additions & 0 deletions test/resolver/issue282/output.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
openapi: 3.0.0
info:
version: 1.0.0
title: Swagger Petstore
license:
name: MIT
servers:
- url: http://petstore.swagger.io/v1
paths:
/pets:
get:
summary: List all pets
operationId: listPets
tags:
- pets
parameters:
- name: limit
in: query
description: How many items to return at one time (max 100)
required: false
schema:
type: integer
format: int32
responses:
"200":
description: An paged array of pets
headers:
x-next:
description: A link to the next page of responses
schema:
type: string
content:
application/json:
schema:
type: object
required:
- id
- name
properties:
id:
type: integer
format: int64
name:
type: string
tag:
type: string
post:
summary: Create pet
tags:
- pets
parameters:
- name: limit
in: query
description: How many items to return at one time (max 100)
required: false
schema:
type: integer
format: int32
responses:
"200":
description: An paged array of pets
content:
application/json:
schema:
type: object
required:
- id
- name
properties:
id:
type: integer
format: int64
name:
type: string
tag:
type: string
"400":
content:
application/json:
schema:
$ref: incorrect-ref.yaml
12 changes: 12 additions & 0 deletions test/resolver/issue282/pet.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
type: object
required:
- id
- name
properties:
id:
type: integer
format: int64
name:
type: string
tag:
type: string

0 comments on commit e142702

Please sign in to comment.