Skip to content

Commit

Permalink
fix: make query parameters optional when matching and match them on p…
Browse files Browse the repository at this point in the history
…artial match
  • Loading branch information
troch committed Sep 4, 2015
1 parent 5ba3871 commit 303b240
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 13 deletions.
37 changes: 28 additions & 9 deletions modules/Path.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,17 @@ let optTrailingSlash = (source, trailingSlash) => {
return source.replace(/\\\/$/, '') + '(?:\\/)?'
}

let parseQueryParams = path => {
let searchPart = path.split('?')[1]
if (!searchPart) return {}
return searchPart.split('&')
.map(_ => _.split('='))
.reduce((obj, m) => {
obj[m[0]] = m[1] === undefined ? '' : m[1]
return obj
}, {})
}

let isSerialisable = val => val !== undefined && val !== null && val !== ''

export default class Path {
Expand Down Expand Up @@ -132,15 +143,11 @@ export default class Path {
// If no match, or no query params, no need to go further
if (!match || !this.hasQueryParams) return match
// Extract query params
let queryParams = path.split('?')[1].split('&')
.map(_ => _.split('='))
.reduce((obj, m) => {
obj[m[0]] = m[1] === undefined ? '' : m[1]
return obj
}, {})
let queryParams = parseQueryParams(path)
let unexpectedQueryParams = Object.keys(queryParams)
.filter(p => this.queryParams.indexOf(p) === -1)

if (Object.keys(queryParams).every(p => Object.keys(this.queryParams).indexOf(p) !== 1)
&& Object.keys(queryParams).length === this.queryParams.length) {
if (unexpectedQueryParams.length === 0) {
// Extend url match
Object.keys(queryParams)
.forEach(p => match[p] = queryParams[p])
Expand All @@ -155,7 +162,19 @@ export default class Path {
// Check if partial match (start of given path matches regex)
// trailingSlash: falsy => non optional, truthy => optional
let source = optTrailingSlash(this.source, trailingSlash)
return this._urlMatch(path, new RegExp('^' + source))
let match = this._urlMatch(path, new RegExp('^' + source))

if (!match) return match

if (!this.hasQueryParams) return match

let queryParams = parseQueryParams(path)

Object.keys(queryParams)
.filter(p => this.queryParams.indexOf(p) >= 0)
.forEach(p => match[p] = queryParams[p])

return match
}

build(params = {}, opts = {ignoreConstraints: false, ignoreSearch: false}) {
Expand Down
10 changes: 6 additions & 4 deletions test/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,18 +47,20 @@ describe('Path', function () {
// Successful match & partial match
path.match('/users?offset=31&limit=15').should.eql({ offset: '31', limit: '15' });
path.match('/users?offset&limit=15').should.eql({ offset: '', limit: '15' });
// path.partialMatch('/users').should.eql({});
path.match('/users?limit=15').should.eql({ limit: '15' });
path.partialMatch('/users?offset&limits=1').should.eql({ offset: '' });
path.partialMatch('/users').should.eql({});

// Unsuccessful match
should.not.exist(path.match('/users?offset=31'));
should.not.exist(path.match('/users?limit=15'));
should.not.exist(path.match('/users?offset=31&order=asc'));
should.not.exist(path.match('/users?offset=31&limit=10&order=asc'));

path.build({ offset: 31, limit: 15 }).should.equal('/users?offset=31&limit=15');
path.build({ offset: 31 }).should.equal('/users?offset=31');
path.build({ offset: 31, limit: '' }).should.equal('/users?offset=31&limit');
path.build({ offset: 31, limit: undefined }).should.equal('/users?offset=31&limit');
path.build({ offset: 31, limit: false }).should.equal('/users?offset=31&limit=false');
path.build({ offset: 31, limit: 15 }, {ignoreSearch: true}).should.equal('/users');

});

it('should match and build paths with url and query parameters', function () {
Expand Down

0 comments on commit 303b240

Please sign in to comment.