diff --git a/package.json b/package.json index 4fe863a3a..2f37210e8 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,7 @@ "xmock": "^0.3.0" }, "dependencies": { + "@kyleshockey/object-assign-deep": "^0.4.0", "babel-runtime": "^6.23.0", "btoa": "1.1.2", "cookie": "^0.3.1", @@ -77,8 +78,8 @@ "isomorphic-form-data": "0.0.1", "js-yaml": "^3.8.1", "lodash": "^4.16.2", - "@kyleshockey/object-assign-deep": "^0.4.0", "qs": "^6.3.0", + "querystring-browser": "^1.0.4", "url": "^0.11.0", "utf8-bytes": "0.0.1", "utfstring": "^2.0.0" diff --git a/src/specmap/lib/refs.js b/src/specmap/lib/refs.js index 44ecc4512..b32d25af4 100644 --- a/src/specmap/lib/refs.js +++ b/src/specmap/lib/refs.js @@ -1,4 +1,5 @@ import {fetch} from 'cross-fetch' +import qs from 'querystring-browser' import url from 'url' import lib from '../lib' import createError from '../lib/create-error' @@ -303,7 +304,7 @@ function unescapeJsonPointerToken(token) { if (typeof token !== 'string') { return token } - return token.replace(/~1/g, '/').replace(/~0/g, '~') + return qs.unescape(token.replace(/~1/g, '/').replace(/~0/g, '~')) } /** @@ -311,7 +312,7 @@ function unescapeJsonPointerToken(token) { * @api public */ function escapeJsonPointerToken(token) { - return token.replace(/~/g, '~0').replace(/\//g, '~1') + return qs.escape(token.replace(/~/g, '~0').replace(/\//g, '~1')) } function arrayToJsonPointer(arr) { diff --git a/test/resolver.js b/test/resolver.js index 99052a46c..e551a0c0c 100644 --- a/test/resolver.js +++ b/test/resolver.js @@ -48,6 +48,69 @@ describe('resolver', () => { } }) + it('should be able to resolve $refs with percent-encoded values', () => { + // Given + const spec = { + one: { + uno: 1, + $ref: '#/value%20two' + }, + 'value two': { + duos: 2 + } + } + + // When + return Swagger.resolve({spec, allowMetaPatches: false}) + .then(handleResponse) + + // Then + function handleResponse(obj) { + expect(obj.errors).toEqual([]) + expect(obj.spec).toEqual({ + one: { + duos: 2 + }, + 'value two': { + duos: 2 + } + }) + } + }) + + it('should tolerate $refs with raw values that should be percent-encoded', () => { + // NOTE: this is for compatibility and can be removed in the next major + // REVIEW for v4 + + // Given + const spec = { + one: { + uno: 1, + $ref: '#/value two' + }, + 'value two': { + duos: 2 + } + } + + // When + return Swagger.resolve({spec, allowMetaPatches: false}) + .then(handleResponse) + + // Then + function handleResponse(obj) { + expect(obj.errors).toEqual([]) + expect(obj.spec).toEqual({ + one: { + duos: 2 + }, + 'value two': { + duos: 2 + } + }) + } + }) + it('should be able to resolve circular $refs when a baseDoc is provided', () => { // Given const spec = {