From ad78625271f38b0ead254e040d8deaeb0581ea9f Mon Sep 17 00:00:00 2001 From: Luis Tejeda <46000487+LuisTejedaS@users.noreply.github.com> Date: Wed, 13 Jul 2022 14:39:23 -0500 Subject: [PATCH] Add support for url with fragment and servers Add support for url with fragment and serversAdd support for url with fragment and serversAdd support for url with fragment and servers --- lib/schemaUtils.js | 17 +++- .../explicit_server_in_path.json | 77 +++++++++++++++++++ test/unit/validator.test.js | 39 ++++++++++ 3 files changed, 129 insertions(+), 4 deletions(-) diff --git a/lib/schemaUtils.js b/lib/schemaUtils.js index 1c688ce..14bff68 100644 --- a/lib/schemaUtils.js +++ b/lib/schemaUtils.js @@ -2603,6 +2603,7 @@ module.exports = { matchedPath, matchedPathJsonPath, schemaPathItems = schema.paths, + pathToMatchServer, filteredPathItemsArray = []; // Return no matches for invalid url (if unable to decode parsed url) @@ -2650,9 +2651,12 @@ module.exports = { // check if path and pathToMatch match (non-null) // check in explicit (local defined) servers if (pathItemObject[method.toLowerCase()].servers) { - pathToMatch = this.handleExplicitServersPathToMatch(pathToMatch, path); + pathToMatchServer = this.handleExplicitServersPathToMatch(pathToMatch, path); + schemaMatchResult = this.getPostmanUrlSchemaMatchScore(pathToMatchServer, path, options); + } + else { + schemaMatchResult = this.getPostmanUrlSchemaMatchScore(pathToMatch, path, options); } - schemaMatchResult = this.getPostmanUrlSchemaMatchScore(pathToMatch, path, options); if (!schemaMatchResult.match) { // there was no reasonable match b/w the postman path and this schema path return true; @@ -4446,6 +4450,7 @@ module.exports = { */ handleExplicitServersPathToMatch: function (pathToMatch, schemaPath) { let pathTMatchSlice, + fragment = '', schemaPathArr = _.reject(schemaPath.split('/'), (segment) => { return segment === ''; }), @@ -4453,12 +4458,16 @@ module.exports = { pathToMatchArr = _.reject(pathToMatch.split('/'), (segment) => { return segment === ''; }), - pathToMatchSegments = pathToMatchArr.length; + pathToMatchSegments = pathToMatchArr.length, + fragments = schemaPath.split('#'); + if (fragments.length > 1) { + fragment = '#' + fragments[1]; + } if (pathToMatchSegments < schemaPathSegments) { return pathToMatch; } pathTMatchSlice = pathToMatchArr.slice(pathToMatchArr.length - schemaPathSegments, pathToMatchArr.length); - return pathTMatchSlice.join('/'); + return pathTMatchSlice.join('/') + fragment; }, /** diff --git a/test/data/valid_openapi/explicit_server_in_path.json b/test/data/valid_openapi/explicit_server_in_path.json index 828472e..af8181c 100644 --- a/test/data/valid_openapi/explicit_server_in_path.json +++ b/test/data/valid_openapi/explicit_server_in_path.json @@ -313,6 +313,83 @@ } } } + }, + "/oauth2/token#refresh": { + "get": { + "operationId": "get_authorize", + "summary": "Part url", + "description": "Authorize a user.", + "tags": [ + "Authorization" + ], + "security": [], + "servers": [ + { + "url": "https://server/api/oauth2", + "description": "Server for client-side authentication" + } + ], + "parameters": [ + { + "name": "response_type", + "description": "The type of response we'd like to receive.", + "in": "query", + "example": "code", + "required": true, + "schema": { + "type": "string", + "format": "token", + "enum": [ + "code" + ] + } + }, + { + "name": "client_id", + "description": "The Client ID.", + "in": "query", + "example": "ly1nj6n11vionaie65emwzk575hnnmrk", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "scope", + "description": "A comma-separated", + "in": "query", + "example": "admin_readwrite", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Does not return any data, but rather should be used in the browser.", + "content": { + "text/html": { + "schema": { + "type": "string", + "format": "html" + } + } + } + }, + "default": { + "description": "Does not return any data, but rather should be used in the browser.", + "content": { + "text/html": { + "schema": { + "type": "string", + "format": "html" + } + } + } + } + } + } } }, "components": { diff --git a/test/unit/validator.test.js b/test/unit/validator.test.js index e59ec6d..4b2d0dd 100644 --- a/test/unit/validator.test.js +++ b/test/unit/validator.test.js @@ -63,6 +63,44 @@ function getFoldersByVersion(folder30Path, folder31Path) { }]; } +describe('Validate with servers', function () { + it('Fix for GITHUB#497: Should identify url with fragment', function () { + const openAPI = path.join(__dirname, VALID_OPENAPI_FOLDER_PATH + '/explicit_server_in_path.json'), + openAPIData = fs.readFileSync(openAPI, 'utf8'), + options = { + requestParametersResolution: 'Example', + exampleParametersResolution: 'Example', + showMissingInSchemaErrors: true, + strictRequestMatching: true, + ignoreUnresolvedVariables: true, + validateMetadata: true, + suggestAvailableFixes: true, + detailedBlobValidation: false + }, + schemaPack = new Converter.SchemaPack({ type: 'string', data: openAPIData }, options); + schemaPack.convert((err, conversionResult) => { + expect(err).to.be.null; + expect(conversionResult.result).to.equal(true); + + let historyRequest = []; + + getAllTransactions(conversionResult.output[0].data, historyRequest); + + schemaPack.validateTransaction(historyRequest, (err, result) => { + expect(err).to.be.null; + expect(result).to.be.an('object'); + + let requestIds = Object.keys(result.requests); + expect(err).to.be.null; + expect(result.missingEndpoints.length).to.eq(0); + requestIds.forEach((requestId) => { + expect(result.requests[requestId].endpoints[0]).to.not.be.undefined; + expect(result.requests[requestId].endpoints[0].matched).to.be.true; + }); + }); + }); + }); +}); describe('Validation with different resolution parameters options', function () { @@ -1309,3 +1347,4 @@ describe('VALIDATE FUNCTION TESTS ', function () { }); }); }); +