Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: APIDevTools/json-schema-ref-parser
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: main
Choose a base ref
...
head repository: JSCIG/json-schema-ref-parser
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref
Can’t automatically merge. Don’t worry, you can still create the pull request.
  • 6 commits
  • 6 files changed
  • 1 contributor

Commits on Jan 5, 2021

  1. fix: audit fix

    septs committed Jan 5, 2021
    Copy the full SHA
    00181a7 View commit details
  2. Copy the full SHA
    4259b19 View commit details
  3. add preprocessor

    septs committed Jan 5, 2021
    Copy the full SHA
    b9a28df View commit details

Commits on Jan 9, 2021

  1. prettier code

    septs committed Jan 9, 2021
    Copy the full SHA
    c57d6aa View commit details
  2. Copy the full SHA
    842a18b View commit details
  3. update option.md

    septs committed Jan 9, 2021
    Copy the full SHA
    eb9f016 View commit details
Showing with 203 additions and 504 deletions.
  1. +1 −2 docs/options.md
  2. +1 −1 lib/dereference.js
  3. +6 −9 lib/index.d.ts
  4. +19 −115 lib/resolvers/http.js
  5. +174 −376 package-lock.json
  6. +2 −1 package.json
3 changes: 1 addition & 2 deletions docs/options.md
Original file line number Diff line number Diff line change
@@ -63,9 +63,8 @@ JSON Schema $Ref Parser comes with built-in support for HTTP and HTTPS, as well
|`file.order` `http.order`|`number`|Resolvers run in a specific order, relative to other resolvers. For example, a resolver with `order: 5` will run _before_ a resolver with `order: 10`. If a resolver is unable to successfully resolve a path, then the next resolver is tried, until one succeeds or they all fail.<br><br>You can change the order in which resolvers run, which is useful if you know that most of your file references will be a certain type, or if you add [your own custom resolver](plugins/resolvers.md) that you want to run _first_.
|`file.canRead` `http.canRead`|`boolean`, `RegExp`, `string`, `array`, `function`|Determines which resolvers will be used for which files.<br><br>A regular expression can be used to match files by their full path. A string (or array of strings) can be used to match files by their file extension. Or a function can be used to perform more complex matching logic. See the [custom resolver](plugins/resolvers.md) docs for details.
|`http.headers`|`object`|You can specify any HTTP headers that should be sent when downloading files. For example, some servers may require you to set the `Accept` or `Referrer` header.
|`http.timeout` |`number` |The amount of time (in milliseconds) to wait for a response from the server when downloading files. The default is 5 seconds.
|`http.redirects` |`number` |The maximum number of HTTP redirects to follow per file. The default is 5. To disable automatic following of redirects, set this to zero.
|`http.withCredentials`|`boolean`|Set this to `true` if you're downloading files from a CORS-enabled server that requires authentication
|`http.fetch`|`function`|Provide other `window.fetch` polyfill or native implementation


`dereference` Options
2 changes: 1 addition & 1 deletion lib/dereference.js
Original file line number Diff line number Diff line change
@@ -100,7 +100,7 @@ function crawl (obj, path, pathFromRoot, parents, processedObjects, dereferenced
* @param {string} pathFromRoot - The path of `$ref` from the schema root
* @param {object[]} parents - An array of the parent objects that have already been dereferenced
* @param {object[]} processedObjects - An array of all the objects that have already been dereferenced
* @param {object} dereferencedCache - An map of all the dereferenced objects
* @param {object} dereferencedCache - An map of all the dereferenced objects
* @param {$Refs} $refs
* @param {$RefParserOptions} options
* @returns {{value: object, circular: boolean}}
15 changes: 6 additions & 9 deletions lib/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// eslint-disable-next-line
/// <reference lib="dom" />
import { JSONSchema4, JSONSchema4Type, JSONSchema6, JSONSchema6Type } from "json-schema";

export = $RefParser;
@@ -242,19 +244,14 @@ declare namespace $RefParser {
headers?: object;

/**
* The amount of time (in milliseconds) to wait for a response from the server when downloading files. The default is 5 seconds.
*/
timeout?: number;

/**
* The maximum number of HTTP redirects to follow per file. The default is 5. To disable automatic following of redirects, set this to zero.
* Set this to `true` if you're downloading files from a CORS-enabled server that requires authentication
*/
redirects?: number;
withCredentials?: boolean;

/**
* Set this to `true` if you're downloading files from a CORS-enabled server that requires authentication
* Provide `fetch` function
*/
withCredentials?: boolean;
fetch: typeof globalThis["fetch"];
}

/**
134 changes: 19 additions & 115 deletions lib/resolvers/http.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
"use strict";

const http = require("http");
const https = require("https");
const { ono } = require("@jsdevtools/ono");
const url = require("../util/url");
const { ResolverError } = require("../util/errors");
@@ -27,21 +25,6 @@ module.exports = {
*/
headers: null,

/**
* HTTP request timeout (in milliseconds).
*
* @type {number}
*/
timeout: 5000, // 5 seconds

/**
* The maximum number of HTTP redirects to follow.
* To disable automatic following of redirects, set this to zero.
*
* @type {number}
*/
redirects: 5,

/**
* The `withCredentials` option of XMLHttpRequest.
* Set this to `true` if you're downloading files from a CORS-enabled server that requires authentication
@@ -50,6 +33,13 @@ module.exports = {
*/
withCredentials: false,

/**
* Provde `fetch` implementation
*
* @type {globalThis['fetch']} fetcher
*/
fetch: require("isomorphic-fetch"),

/**
* Determines whether this resolver can read a given file reference.
* Resolvers that return true will be tried in order, until one successfully resolves the file.
@@ -70,7 +60,7 @@ module.exports = {
* @param {object} file - An object containing information about the referenced file
* @param {string} file.url - The full URL of the referenced file
* @param {string} file.extension - The lowercased file extension (e.g. ".txt", ".html", etc.)
* @returns {Promise<Buffer>}
* @returns {Promise<string>}
*/
read (file) {
let u = url.parse(file.url);
@@ -80,101 +70,15 @@ module.exports = {
u.protocol = url.parse(location.href).protocol;
}

return download(u, this);
}
};

/**
* Downloads the given file.
*
* @param {Url|string} u - The url to download (can be a parsed {@link Url} object)
* @param {object} httpOptions - The `options.resolve.http` object
* @param {number} [redirects] - The redirect URLs that have already been followed
*
* @returns {Promise<Buffer>}
* The promise resolves with the raw downloaded data, or rejects if there is an HTTP error.
*/
function download (u, httpOptions, redirects) {
return new Promise(((resolve, reject) => {
u = url.parse(u);
redirects = redirects || [];
redirects.push(u.href);

get(u, httpOptions)
.then((res) => {
if (res.statusCode >= 400) {
throw ono({ status: res.statusCode }, `HTTP ERROR ${res.statusCode}`);
}
else if (res.statusCode >= 300) {
if (redirects.length > httpOptions.redirects) {
reject(new ResolverError(ono({ status: res.statusCode },
`Error downloading ${redirects[0]}. \nToo many redirects: \n ${redirects.join(" \n ")}`)));
}
else if (!res.headers.location) {
throw ono({ status: res.statusCode }, `HTTP ${res.statusCode} redirect with no location header`);
}
else {
// console.log('HTTP %d redirect %s -> %s', res.statusCode, u.href, res.headers.location);
let redirectTo = url.resolve(u, res.headers.location);
download(redirectTo, httpOptions, redirects).then(resolve, reject);
}
}
else {
resolve(res.body || Buffer.alloc(0));
}
})
.catch((err) => {
reject(new ResolverError(ono(err, `Error downloading ${u.href}`), u.href));
});
}));
}

/**
* Sends an HTTP GET request.
*
* @param {Url} u - A parsed {@link Url} object
* @param {object} httpOptions - The `options.resolve.http` object
*
* @returns {Promise<Response>}
* The promise resolves with the HTTP Response object.
*/
function get (u, httpOptions) {
return new Promise(((resolve, reject) => {
// console.log('GET', u.href);

let protocol = u.protocol === "https:" ? https : http;
let req = protocol.get({
hostname: u.hostname,
port: u.port,
path: u.path,
auth: u.auth,
protocol: u.protocol,
headers: httpOptions.headers || {},
withCredentials: httpOptions.withCredentials
});

if (typeof req.setTimeout === "function") {
req.setTimeout(httpOptions.timeout);
}
/** @type {RequestInit} */
const init = {
method: "GET",
headers: this.headers,
credentials: this.withCredentials ? "include" : "omit",
};

req.on("timeout", () => {
req.abort();
});

req.on("error", reject);

req.once("response", (res) => {
res.body = Buffer.alloc(0);

res.on("data", (data) => {
res.body = Buffer.concat([res.body, Buffer.from(data)]);
});

res.on("error", reject);

res.on("end", () => {
resolve(res);
});
});
}));
}
return this.fetch(url.format(u), init)
.then((response) => response.text())
.catch((err) => new ResolverError(ono(err, `Error downloading ${u.href}`), u.href));
},
};
Loading