Skip to content

Commit

Permalink
Fixed URL path extraction with media type extension
Browse files Browse the repository at this point in the history
  • Loading branch information
shubhbhargav committed May 24, 2022
1 parent d3392cb commit 1df7a51
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 21 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
unreleased:
chores:
- Run Travis coverage step in latest LTS Node.js release
fixed bugs:
- >-
GH-1268 Fixed a bug where URL path variables are not replaced if followed
by a dot
4.1.2:
date: 2022-03-28
Expand Down
39 changes: 27 additions & 12 deletions lib/collection/url.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ var _ = require('../util').lodash,
HTTPS_PORT = '443',
HTTP_PORT = '80',
PATH_SEPARATOR = '/',
PATH_VARIABLE_SEPARATOR = '.',
PATH_VARIABLE_IDENTIFIER = ':',
PORT_SEPARATOR = ':',
DOMAIN_SEPARATOR = '.',
Expand All @@ -31,6 +32,24 @@ var _ = require('../util').lodash,
splitDomain: /\.(?![^{]*\}{2})/g
},

/**
* Returns path variable name from the path segment.
*
* @private
* @param {String} pathSegment -
* @returns {String|null}
*/
parsePathVariable = function (pathSegment) {
if (String(pathSegment).startsWith(PATH_VARIABLE_IDENTIFIER)) {
const separatorIndex = pathSegment.indexOf(PATH_VARIABLE_SEPARATOR);

// remove path variable prefix and everything followed by the separator
return pathSegment.slice(1, separatorIndex === -1 ? undefined : separatorIndex) || null;
}

return null;
},

Url;

_.inherit((
Expand Down Expand Up @@ -273,15 +292,15 @@ _.assign(Url.prototype, /** @lends Url.prototype */ {
segments;

segments = _.transform(this.path, function (res, segment) {
var variable;
const variableKey = parsePathVariable(segment),
variableValue = self.variables.get(variableKey);

// check if the segment has path variable prefix followed by the variable name.
if (_.startsWith(segment, PATH_VARIABLE_IDENTIFIER) && segment !== PATH_VARIABLE_IDENTIFIER) {
variable = self.variables.one(segment.slice(1)); // remove path variable prefix.
if (variableValue && typeof variableValue === STRING) {
// replace the variable with its value while preserving the suffix
segment = variableValue + segment.slice(variableKey.length + 1);
}

variable = variable && variable.valueOf && variable.valueOf();
res.push(_.isString(variable) ? variable : segment);
res.push(segment);
}, []);

return PATH_SEPARATOR + segments.join(PATH_SEPARATOR); // add leading slash
Expand Down Expand Up @@ -413,13 +432,9 @@ _.assign(Url, /** @lends Url */ {

// extract path variables
pathVariables = _.transform(url.path, function (res, segment) {
// check if the segment has path variable prefix followed by the variable name and
// the variable is not already added in the list.
if (_.startsWith(segment, PATH_VARIABLE_IDENTIFIER) &&
segment !== PATH_VARIABLE_IDENTIFIER &&
!pathVariableKeys[segment]) {
if ((segment = parsePathVariable(segment)) && !pathVariableKeys[segment]) {
pathVariableKeys[segment] = true;
res.push({ key: segment.slice(1) }); // remove path variable prefix.
res.push({ key: segment });
}
}, []);
url.variable = pathVariables.length ? pathVariables : undefined;
Expand Down
64 changes: 55 additions & 9 deletions test/unit/url.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -545,14 +545,30 @@ describe('Url', function () {
var subject = Url.parse('http://127.0.0.1/:a/:ab.json/:a+b');

expect(subject).to.have.property('variable').that.has.lengthOf(3).that.eql([
{ key: 'a' }, { key: 'ab.json' }, { key: 'a+b' }
{ key: 'a' }, { key: 'ab' }, { key: 'a+b' }
]);
});

it('should parse path variables with media type extension', function () {
var subject = Url.parse('http://127.0.0.1/:a/:ab.json');

expect(subject).to.have.property('variable').that.has.lengthOf(2).that.eql([
{ key: 'a' }, { key: 'ab' }
]);
});

it('should ignore everything after a dot in path variable', function () {
var subject = Url.parse('http://127.0.0.1/:foo.bar.baz');

expect(subject).to.have.property('variable').that.has.lengthOf(1).that.eql([
{ key: 'foo' }
]);
});

it('should not parse empty path variables', function () {
var subject = Url.parse('http://127.0.0.1/:/:/:var');
var subject = Url.parse('http://127.0.0.1/:/:./:var');

expect(subject.path).to.eql([':', ':', ':var']);
expect(subject.path).to.eql([':', ':.', ':var']);
expect(subject.variable).to.have.lengthOf(1).that.eql([{ key: 'var' }]);
});

Expand All @@ -565,10 +581,10 @@ describe('Url', function () {
});

it('should parse path variables containing special characters properly', function () {
var subject = Url.parse('http://127.0.0.1/:郵差/:foo.json');
var subject = Url.parse('http://127.0.0.1/:郵差/:foo-郵差.json');

expect(subject).to.have.property('variable').that.has.lengthOf(2).that.eql([
{ key: '郵差' }, { key: 'foo.json' }
{ key: '郵差' }, { key: 'foo-郵差' }
]);
});

Expand Down Expand Up @@ -1004,6 +1020,35 @@ describe('Url', function () {
expect(url.getPath()).to.eql('/get/:beta/:gamma/:delta/:epsilon/:phi');
});

it('should work with media type extension', function () {
var url = new Url({
protocol: 'https',
host: 'postman-echo.com',
port: '443',
path: '/:alpha/:beta.json',
variable: [
{ key: 'alpha', value: 'foo' },
{ key: 'beta', value: 'bar' }
]
});

expect(url.getPath()).to.eql('/foo/bar.json');
});

it('should ignore everything after a dot', function () {
var url = new Url({
protocol: 'https',
host: 'postman-echo.com',
port: '443',
path: '/:郵差.bar.baz',
variable: [
{ key: '郵差', value: 'foo' }
]
});

expect(url.getPath()).to.eql('/foo.bar.baz');
});

it('should not resolve path variables when unresolved is set to false', function () {
var url = new Url({
protocol: 'https',
Expand Down Expand Up @@ -1116,22 +1161,23 @@ describe('Url', function () {
});

it('should handle path variables', function () {
var url = 'http://127.0.0.1/:郵差/:/:foo.json';
var url = 'http://127.0.0.1/:郵差/:/:./:foo.bar.baz/:foo.json';

expect((new Url(url)).toString()).to.equal(url);
});

it('should resolve path variables', function () {
var url = new Url({
host: 'localhost',
path: '/:v1/:/:郵差',
path: '/:v1/:/:./:郵差/:郵差-郵差.1.json',
variable: [
{ key: 'v1', value: 'foo' },
{ key: '郵差', value: 'bar' }
{ key: '郵差', value: 'bar' },
{ key: '郵差-郵差', value: 'baz' }
]
});

expect(url.toString()).to.equal('localhost/foo/:/bar');
expect(url.toString()).to.equal('localhost/foo/:/:./bar/baz.1.json');
});

it('should handle variables having reserved characters', function () {
Expand Down

0 comments on commit 1df7a51

Please sign in to comment.