Skip to content

Commit

Permalink
feat: parseFromUrl does not resolve relative references (asyncapi#504)
Browse files Browse the repository at this point in the history
  • Loading branch information
aeworxet committed Jul 18, 2022
1 parent c962a7e commit e7d657a
Showing 1 changed file with 26 additions and 14 deletions.
40 changes: 26 additions & 14 deletions lib/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,12 @@ module.exports = {

/**
* Parses and validate an AsyncAPI document from YAML or JSON.
*
*
* @param {(String | Object)} asyncapiYAMLorJSON An AsyncAPI document in JSON or YAML format.
* @param {ParserOptions=} options Configuration options object {@link #asyncapiparserparseroptions--object|ParserOptions}
* @returns {Promise<AsyncAPIDocument>} The parsed AsyncAPI document.
*/
async function parse(asyncapiYAMLorJSON, options = {}) {
async function parse(asyncapiYAMLorJSON, options = {}, urlRegExped) {
let parsedJSON;
let initialFormat;

Expand All @@ -67,15 +67,15 @@ async function parse(asyncapiYAMLorJSON, options = {}) {
detail: 'Most probably the AsyncAPI document contains invalid YAML or YAML features not supported in JSON.'
});
}

if (!parsedJSON.asyncapi) {
throw new ParserError({
type: 'missing-asyncapi-field',
title: 'The `asyncapi` field is missing.',
parsedJSON,
});
}

if (parsedJSON.asyncapi.startsWith('1.') || !asyncapi[parsedJSON.asyncapi]) {
throw new ParserError({
type: 'unsupported-version',
Expand Down Expand Up @@ -121,7 +121,7 @@ async function parse(asyncapiYAMLorJSON, options = {}) {

/**
* Fetches an AsyncAPI document from the given URL and passes its content to the `parse` method.
*
*
* @param {String} url URL where the AsyncAPI document is located.
* @param {Object=} [fetchOptions] Configuration to pass to the {@link https://developer.mozilla.org/en-US/docs/Web/API/Request|fetch} call.
* @param {ParserOptions=} [options] Configuration to pass to the {@link #asyncapiparserparseroptions--object|ParserOptions} method.
Expand All @@ -133,10 +133,22 @@ function parseFromUrl(url, fetchOptions, options) {
//To not break the API by changing argument position and to silet the linter it is just better to move adding
if (!fetchOptions) fetchOptions = {};

// RegExp to choose name of YAML file in the URL string is created.
const regexp = /[^/]+$/g;
// When executed in multiple async calls, 'checkErrorWrapper' passes URL
// string as object by reference. In this case 'String.replace()' method
// mutates original URL string causing test with multiple async calls to fail.
// Thus fully independent object containing URL string is created for future
// manipulation.
const urlCopy = new String(url);
// In the copy of the URL string name of a YAML file with spec is replaced
// with zero, leaving only part of absolute URL before final slash.
const urlRegExped = urlCopy.replace(regexp.exec(urlCopy), '');

return new Promise((resolve, reject) => {
fetch(url, fetchOptions)
.then(res => res.text())
.then(doc => parse(doc, options))
.then(doc => parse(doc, options, urlRegExped))
.then(result => resolve(result))
.catch(e => {
if (e instanceof ParserError) return reject(e);
Expand Down Expand Up @@ -178,7 +190,7 @@ async function handleCircularRefs(refParser, parsedJSON, initialFormat, asyncapi

/**
* Creates (or reuses) a function that validates an AsyncAPI document based on the passed AsyncAPI version.
*
*
* @private
* @param {Object} version AsyncAPI version.
* @returns {Function} Function that validates an AsyncAPI document based on the passed AsyncAPI version.
Expand Down Expand Up @@ -219,7 +231,7 @@ async function validateAndConvertMessage(msg, originalAsyncAPIDocument, fileForm
defaultSchemaFormat,
originalAsyncAPIDocument,
parsedAsyncAPIDocument,
fileFormat,
fileFormat,
pathToPayload
});

Expand All @@ -229,12 +241,12 @@ async function validateAndConvertMessage(msg, originalAsyncAPIDocument, fileForm

/**
* Registers a new schema parser. Schema parsers are in charge of parsing and transforming payloads to AsyncAPI Schema format.
*
*
* @param {Object} parserModule The schema parser module containing parse() and getMimeTypes() functions.
*/
function registerSchemaParser(parserModule) {
if (typeof parserModule !== 'object'
|| typeof parserModule.parse !== 'function'
if (typeof parserModule !== 'object'
|| typeof parserModule.parse !== 'function'
|| typeof parserModule.getMimeTypes !== 'function')
throw new ParserError({
type: 'impossible-to-register-parser',
Expand Down Expand Up @@ -263,7 +275,7 @@ function applyTraits(js) {
* Triggers additional operations on the AsyncAPI channels like traits application or message validation and conversion
*
* @private
*
*
* @param {Object} parsedJSON parsed AsyncAPI document
* @param {String} asyncapiYAMLorJSON AsyncAPI document in string
* @param {String} initialFormat information of the document was originally JSON or YAML
Expand All @@ -277,7 +289,7 @@ async function customChannelsOperations(parsedJSON, asyncapiYAMLorJSON, initialF
if (!op) return;

const messages = op.message ? (op.message.oneOf || [op.message]) : [];
if (options.applyTraits) {
if (options.applyTraits) {
applyTraits(op);
messages.forEach(m => applyTraits(m));
}
Expand All @@ -294,7 +306,7 @@ async function customChannelsOperations(parsedJSON, asyncapiYAMLorJSON, initialF
* Triggers additional operations on the AsyncAPI messages located in the components section of the document. It triggers operations like traits application, validation and conversion
*
* @private
*
*
* @param {Object} parsedJSON parsed AsyncAPI document
* @param {String} asyncapiYAMLorJSON AsyncAPI document in string
* @param {String} initialFormat information of the document was originally JSON or YAML
Expand Down

0 comments on commit e7d657a

Please sign in to comment.