diff --git a/README.md b/README.md index ac55415..d077857 100644 --- a/README.md +++ b/README.md @@ -156,6 +156,14 @@ router.on('GET', '/', (req, res, params, store, searchParams) => { router.lookup({ method: 'GET', url: '/?foo=bar&baz=faz' }, null) ``` +According to [RFC3986](https://www.rfc-editor.org/rfc/rfc3986#section-3.4), find-my-way separates path and query string with `?` character. But earlier versions also used `;` as delimiter character. To support this behaviour, add the `useSemicolonDelimiter` option to `true`: + +```js +const router = require('find-my-way')({ + useSemicolonDelimiter: true +}) +``` + You can assign a `buildPrettyMeta` function to sanitize a route's `store` object to use with the `prettyPrint` functions. This function should accept a single object and return an object. ```js diff --git a/index.js b/index.js index a0a8400..366ec83 100644 --- a/index.js +++ b/index.js @@ -88,6 +88,7 @@ function Router (opts) { this.maxParamLength = opts.maxParamLength || 100 this.allowUnsafeRegex = opts.allowUnsafeRegex || false this.constrainer = new Constrainer(opts.constraints) + this.useSemicolonDelimiter = opts.useSemicolonDelimiter || false this.routes = [] this.trees = {} @@ -569,7 +570,7 @@ Router.prototype.find = function find (method, path, derivedConstraints) { let shouldDecodeParam try { - sanitizedUrl = safeDecodeURI(path) + sanitizedUrl = safeDecodeURI(path, this.useSemicolonDelimiter) path = sanitizedUrl.path querystring = sanitizedUrl.querystring shouldDecodeParam = sanitizedUrl.shouldDecodeParam diff --git a/lib/url-sanitizer.js b/lib/url-sanitizer.js index c124e8e..8852f9f 100644 --- a/lib/url-sanitizer.js +++ b/lib/url-sanitizer.js @@ -34,7 +34,7 @@ function decodeComponentChar (highCharCode, lowCharCode) { return null } -function safeDecodeURI (path) { +function safeDecodeURI (path, useSemicolonDelimiter) { let shouldDecode = false let shouldDecodeParam = false @@ -61,8 +61,8 @@ function safeDecodeURI (path) { } // Some systems do not follow RFC and separate the path and query // string with a `;` character (code 59), e.g. `/foo;jsessionid=123456`. - // Thus, we need to split on `;` as well as `?` and `#`. - } else if (charCode === 63 || charCode === 59 || charCode === 35) { + // Thus, we need to split on `;` as well as `?` and `#` if the useSemicolonDelimiter option is enabled. + } else if (charCode === 63 || charCode === 35 || (charCode === 59 && useSemicolonDelimiter)) { querystring = path.slice(i + 1) path = path.slice(0, i) break diff --git a/test/querystring.test.js b/test/querystring.test.js index cf015c6..e03020d 100644 --- a/test/querystring.test.js +++ b/test/querystring.test.js @@ -28,9 +28,11 @@ test('should sanitize the url - hash', t => { findMyWay.lookup({ method: 'GET', url: '/test#hello', headers: {} }, null) }) -test('handles path and query separated by ;', t => { +test('handles path and query separated by ; with useSemicolonDelimiter enabled', t => { t.plan(2) - const findMyWay = FindMyWay() + const findMyWay = FindMyWay({ + useSemicolonDelimiter: true + }) findMyWay.on('GET', '/test', (req, res, params, store, query) => { t.same(query, { jsessionid: '123456' }) @@ -39,3 +41,15 @@ test('handles path and query separated by ;', t => { findMyWay.lookup({ method: 'GET', url: '/test;jsessionid=123456', headers: {} }, null) }) + +test('handles path and query separated by ? using ; in the path', t => { + t.plan(2) + const findMyWay = FindMyWay() + + findMyWay.on('GET', '/test;jsessionid=123456', (req, res, params, store, query) => { + t.same(query, { foo: 'bar' }) + t.ok('inside the handler') + }) + + findMyWay.lookup({ method: 'GET', url: '/test;jsessionid=123456?foo=bar', headers: {} }, null) +})