From af0d2d4fe44fbe30a19ed2b63ba3c03ae0e8490a Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Fri, 16 Jun 2017 14:14:59 +0200 Subject: [PATCH] fix(uri template): Escape variables --- CHANGELOG.md | 2 ++ src/uri-template.js | 17 ++++++++++------- test/uri-template.js | 8 ++++---- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0664058..223f4c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ - Parameters which define both an example (`x-example`) and `items` schema will now use the `x-example` value as the example. +- URI Template variables are now correctly escaped. + # 0.12.0-beta.2 ## Bug Fixes diff --git a/src/uri-template.js b/src/uri-template.js index e602c08..17594d5 100644 --- a/src/uri-template.js +++ b/src/uri-template.js @@ -1,26 +1,29 @@ import _ from 'lodash'; +function escapeUriTemplateVariable(variable) { + return encodeURIComponent(variable) + .replace(/[-.!~*'()]/g, c => `%${c.charCodeAt(0).toString(16)}`); +} + export default function buildUriTemplate(basePath, href, pathObjectParams = [], queryParams = []) { const parameterNames = _.chain(pathObjectParams) .concat(queryParams) .filter(parameter => parameter.in === 'query') .uniqBy(parameter => parameter.name) .map((parameter) => { + const name = escapeUriTemplateVariable(parameter.name); + if (parameter.collectionFormat === 'multi') { - return `${parameter.name}*`; + return `${name}*`; } - return parameter.name; + return name; }) .value(); if (parameterNames.length > 0) { const queryString = parameterNames.join(','); - const full = `${basePath}${href}{?${queryString}}`; - - // Before returning, we replace instances of `-` with `%2d`, but only when - // they occur inside of a template variable. - return full.replace(/\{.*?\}/g, match => match.replace('-', '%2d')); + return `${basePath}${href}{?${queryString}}`; } return basePath + href; diff --git a/test/uri-template.js b/test/uri-template.js index 7466615..673beeb 100644 --- a/test/uri-template.js +++ b/test/uri-template.js @@ -94,14 +94,14 @@ describe('URI Template Handler', () => { }); }); - context('when there are parameters with dashes', () => { + context('when there are parameters with reserved characters', () => { const basePath = '/my-api'; - const href = '/pet/{unique-id}'; + const href = '/pet/{unique%2did}'; const queryParams = [ { in: 'query', description: 'Tags to filter by', - name: 'tag-names', + name: 'tag-names[]', required: true, type: 'string', }, @@ -109,7 +109,7 @@ describe('URI Template Handler', () => { it('returns the correct URI', () => { const hrefForResource = buildUriTemplate(basePath, href, [], queryParams); - expect(hrefForResource).to.equal('/my-api/pet/{unique%2did}{?tag%2dnames}'); + expect(hrefForResource).to.equal('/my-api/pet/{unique%2did}{?tag%2dnames%5B%5D}'); }); });