Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

find-my-way

Package Overview
Dependencies
Maintainers
2
Versions
112
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

find-my-way - npm Package Compare versions

Comparing version 5.1.1 to 5.2.0

bench-thread.js

344

bench.js
'use strict'
const Benchmark = require('benchmark')
// The default number of samples for Benchmark seems to be low enough that it
// can generate results with significant variance (~2%) for this benchmark
// suite. This makes it sometimes a bit confusing to actually evaluate impact of
// changes on performance. Setting the minimum of samples to 500 results in
// significantly lower variance on my local setup for this tests suite, and
// gives me higher confidence in benchmark results.
Benchmark.options.minSamples = 500
const path = require('path')
const { Worker } = require('worker_threads')
const suite = Benchmark.Suite()
const BENCH_THREAD_PATH = path.join(__dirname, 'bench-thread.js')
const FindMyWay = require('./')
const testCases = [
{
name: 'lookup root "/" route',
setupURLs: [{ method: 'GET', url: '/' }],
testingMethodName: 'lookup',
args: [
{ method: 'GET', url: '/', headers: { host: 'fastify.io' } },
null
]
},
{
name: 'lookup static route',
setupURLs: [{ method: 'GET', url: '/a' }],
testingMethodName: 'lookup',
args: [
{ method: 'GET', url: '/a', headers: { host: 'fastify.io' } },
null
]
},
{
name: 'lookup dynamic route',
setupURLs: [{ method: 'GET', url: '/user/:id' }],
testingMethodName: 'lookup',
args: [
{ method: 'GET', url: '/user/tomas', headers: { host: 'fastify.io' } },
null
]
},
{
name: 'lookup dynamic multi-parametric route',
setupURLs: [{ method: 'GET', url: '/customer/:name-:surname' }],
testingMethodName: 'lookup',
args: [
{ method: 'GET', url: '/customer/john-doe', headers: { host: 'fastify.io' } },
null
]
},
{
name: 'lookup dynamic multi-parametric route with regex',
setupURLs: [{ method: 'GET', url: '/at/:hour(^\\d+)h:minute(^\\d+)m' }],
testingMethodName: 'lookup',
args: [
{ method: 'GET', url: '/at/12h00m', headers: { host: 'fastify.io' } },
null
]
},
{
name: 'lookup long static route',
setupURLs: [{ method: 'GET', url: '/abc/def/ghi/lmn/opq/rst/uvz' }],
testingMethodName: 'lookup',
args: [
{ method: 'GET', url: '/abc/def/ghi/lmn/opq/rst/uvz', headers: { host: 'fastify.io' } },
null
]
},
{
name: 'lookup long dynamic route',
setupURLs: [{ method: 'GET', url: '/user/:id/static' }],
testingMethodName: 'lookup',
args: [
{
method: 'GET',
url: '/user/qwertyuiopasdfghjklzxcvbnm/static',
headers: { host: 'fastify.io' }
},
null
]
},
{
name: 'lookup static route on constrained router',
setupURLs: [
{ method: 'GET', url: '/' },
{ method: 'GET', url: '/versioned', opts: { constraints: { version: '1.2.0' } } },
{ method: 'GET', url: '/versioned', opts: { constraints: { version: '2.0.0', host: 'example.com' } } },
{ method: 'GET', url: '/versioned', opts: { constraints: { version: '2.0.0', host: 'fastify.io' } } }
],
testingMethodName: 'lookup',
args: [
{
method: 'GET',
url: '/',
headers: { host: 'fastify.io' }
},
null
]
},
{
name: 'lookup static versioned route',
setupURLs: [
{ method: 'GET', url: '/' },
{ method: 'GET', url: '/versioned', opts: { constraints: { version: '1.2.0' } } },
{ method: 'GET', url: '/versioned', opts: { constraints: { version: '2.0.0', host: 'example.com' } } },
{ method: 'GET', url: '/versioned', opts: { constraints: { version: '2.0.0', host: 'fastify.io' } } }
],
testingMethodName: 'lookup',
args: [
{
method: 'GET',
url: '/versioned',
headers: { 'accept-version': '1.x', host: 'fastify.io' }
},
null
]
},
{
name: 'lookup static constrained (version & host) route',
setupURLs: [
{ method: 'GET', url: '/' },
{ method: 'GET', url: '/versioned', opts: { constraints: { version: '1.2.0' } } },
{ method: 'GET', url: '/versioned', opts: { constraints: { version: '2.0.0', host: 'example.com' } } },
{ method: 'GET', url: '/versioned', opts: { constraints: { version: '2.0.0', host: 'fastify.io' } } }
],
testingMethodName: 'lookup',
args: [
{
method: 'GET',
url: '/versioned',
headers: { 'accept-version': '2.x', host: 'fastify.io' }
},
null
]
},
{
name: 'find root "/" route',
setupURLs: [{ method: 'GET', url: '/' }],
testingMethodName: 'find',
args: ['GET', '/']
},
{
name: 'find static route',
setupURLs: [{ method: 'GET', url: '/a' }],
testingMethodName: 'find',
args: ['GET', '/a']
},
{
name: 'find dynamic route',
setupURLs: [{ method: 'GET', url: '/user/:id' }],
testingMethodName: 'find',
args: ['GET', '/user/tomas']
},
{
name: 'find dynamic route with encoded parameter unoptimized',
setupURLs: [{ method: 'GET', url: '/user/:id' }],
testingMethodName: 'find',
args: ['GET', '/user/maintainer%2Btomas']
},
{
name: 'find dynamic route with encoded parameter optimized',
setupURLs: [{ method: 'GET', url: '/user/:id' }],
testingMethodName: 'find',
args: ['GET', '/user/maintainer%20tomas']
},
{
name: 'find dynamic multi-parametric route',
setupURLs: [{ method: 'GET', url: '/customer/:name-:surname' }],
testingMethodName: 'find',
args: ['GET', '/customer/john-doe']
},
{
name: 'find dynamic multi-parametric route with regex',
setupURLs: [{ method: 'GET', url: '/at/:hour(^\\d+)h:minute(^\\d+)m' }],
testingMethodName: 'find',
args: ['GET', '/at/12h00m']
},
{
name: 'find long static route',
setupURLs: [{ method: 'GET', url: '/abc/def/ghi/lmn/opq/rst/uvz' }],
testingMethodName: 'find',
args: ['GET', '/abc/def/ghi/lmn/opq/rst/uvz']
},
{
name: 'find long dynamic route',
setupURLs: [{ method: 'GET', url: '/user/:id/static' }],
testingMethodName: 'find',
args: ['GET', '/user/qwertyuiopasdfghjklzxcvbnm/static']
},
{
name: 'find long nested dynamic route',
setupURLs: [{ method: 'GET', url: '/posts/:id/comments/:id/author' }],
testingMethodName: 'find',
args: ['GET', '/posts/10/comments/42/author']
},
{
name: 'find long nested dynamic route with encoded parameter unoptimized',
setupURLs: [{ method: 'GET', url: '/posts/:id/comments/:id/author' }],
testingMethodName: 'find',
args: ['GET', '/posts/10%2C10/comments/42%2C42/author']
},
{
name: 'find long nested dynamic route with encoded parameter optimized',
setupURLs: [{ method: 'GET', url: '/posts/:id/comments/:id/author' }],
testingMethodName: 'find',
args: ['GET', '/posts/10%2510/comments/42%2542/author']
},
{
name: 'find long nested dynamic route with other method',
setupURLs: [{ method: 'POST', url: '/posts/:id/comments' }],
testingMethodName: 'find',
args: ['POST', '/posts/10/comments']
}
]
const findMyWay = new FindMyWay()
findMyWay.on('GET', '/', () => true)
findMyWay.on('GET', '/user/:id', () => true)
findMyWay.on('GET', '/user/:id/static', () => true)
findMyWay.on('POST', '/user/:id', () => true)
findMyWay.on('PUT', '/user/:id', () => true)
findMyWay.on('GET', '/customer/:name-:surname', () => true)
findMyWay.on('POST', '/customer', () => true)
findMyWay.on('GET', '/at/:hour(^\\d+)h:minute(^\\d+)m', () => true)
findMyWay.on('GET', '/abc/def/ghi/lmn/opq/rst/uvz', () => true)
async function runBenchmark (testCase) {
const worker = new Worker(BENCH_THREAD_PATH, {
workerData: testCase
})
findMyWay.on('GET', '/products', () => true)
findMyWay.on('GET', '/products/:id', () => true)
findMyWay.on('GET', '/products/:id/options', () => true)
return new Promise((resolve, reject) => {
let result = null
worker.on('error', reject)
worker.on('message', (benchResult) => {
result = benchResult
})
worker.on('exit', (code) => {
if (code === 0) {
resolve(result)
} else {
reject(new Error(`Worker stopped with exit code ${code}`))
}
})
})
}
findMyWay.on('GET', '/posts', () => true)
findMyWay.on('POST', '/posts', () => true)
findMyWay.on('GET', '/posts/:id', () => true)
findMyWay.on('GET', '/posts/:id/author', () => true)
findMyWay.on('GET', '/posts/:id/comments', () => true)
findMyWay.on('POST', '/posts/:id/comments', () => true)
findMyWay.on('GET', '/posts/:id/comments/:id', () => true)
findMyWay.on('GET', '/posts/:id/comments/:id/author', () => true)
findMyWay.on('GET', '/posts/:id/counter', () => true)
async function runBenchmarks () {
for (const testCase of testCases) {
const resultMessage = await runBenchmark(testCase)
console.log(resultMessage)
}
}
const constrained = new FindMyWay()
constrained.on('GET', '/', () => true)
constrained.on('GET', '/versioned', () => true)
constrained.on('GET', '/versioned', { constraints: { version: '1.2.0' } }, () => true)
constrained.on('GET', '/versioned', { constraints: { version: '2.0.0', host: 'example.com' } }, () => true)
constrained.on('GET', '/versioned', { constraints: { version: '2.0.0', host: 'fastify.io' } }, () => true)
suite
.add('lookup static route', function () {
findMyWay.lookup({ method: 'GET', url: '/', headers: { host: 'fastify.io' } }, null)
})
.add('lookup dynamic route', function () {
findMyWay.lookup({ method: 'GET', url: '/user/tomas', headers: { host: 'fastify.io' } }, null)
})
.add('lookup dynamic multi-parametric route', function () {
findMyWay.lookup({ method: 'GET', url: '/customer/john-doe', headers: { host: 'fastify.io' } }, null)
})
.add('lookup dynamic multi-parametric route with regex', function () {
findMyWay.lookup({ method: 'GET', url: '/at/12h00m', headers: { host: 'fastify.io' } }, null)
})
.add('lookup long static route', function () {
findMyWay.lookup({ method: 'GET', url: '/abc/def/ghi/lmn/opq/rst/uvz', headers: { host: 'fastify.io' } }, null)
})
.add('lookup long dynamic route', function () {
findMyWay.lookup({ method: 'GET', url: '/user/qwertyuiopasdfghjklzxcvbnm/static', headers: { host: 'fastify.io' } }, null)
})
.add('lookup static route on constrained router', function () {
constrained.lookup({ method: 'GET', url: '/', headers: { host: 'fastify.io' } }, null)
})
.add('lookup static versioned route', function () {
constrained.lookup({ method: 'GET', url: '/versioned', headers: { 'accept-version': '1.x', host: 'fastify.io' } }, null)
})
.add('lookup static constrained (version & host) route', function () {
constrained.lookup({ method: 'GET', url: '/versioned', headers: { 'accept-version': '2.x', host: 'fastify.io' } }, null)
})
.add('find static route', function () {
findMyWay.find('GET', '/', undefined)
})
.add('find dynamic route', function () {
findMyWay.find('GET', '/user/tomas', undefined)
})
.add('find dynamic route with encoded parameter unoptimized', function () {
findMyWay.find('GET', '/user/maintainer%2Btomas', undefined)
})
.add('find dynamic route with encoded parameter optimized', function () {
findMyWay.find('GET', '/user/maintainer%20tomas', undefined)
})
.add('find dynamic multi-parametric route', function () {
findMyWay.find('GET', '/customer/john-doe', undefined)
})
.add('find dynamic multi-parametric route with regex', function () {
findMyWay.find('GET', '/at/12h00m', undefined)
})
.add('find long static route', function () {
findMyWay.find('GET', '/abc/def/ghi/lmn/opq/rst/uvz', undefined)
})
.add('find long dynamic route', function () {
findMyWay.find('GET', '/user/qwertyuiopasdfghjklzxcvbnm/static', undefined)
})
.add('find long nested dynamic route', function () {
findMyWay.find('GET', '/posts/10/comments/42/author', undefined)
})
.add('find long nested dynamic route with encoded parameter unoptimized', function () {
findMyWay.find('GET', '/posts/10%2C10/comments/42%2C42/author', undefined)
})
.add('find long nested dynamic route with encoded parameter optimized', function () {
findMyWay.find('GET', '/posts/10%2510/comments/42%2542/author', undefined)
})
.add('find long nested dynamic route with other method', function () {
findMyWay.find('POST', '/posts/10/comments', undefined)
})
.add('find long nested dynamic route', function () {
findMyWay.find('GET', '/posts/10/comments/42/author', undefined)
})
.add('find long nested dynamic route with other method', function () {
findMyWay.find('POST', '/posts/10/comments', undefined)
})
.on('cycle', function (event) {
console.log(String(event.target))
})
.on('complete', function () {})
.run()
runBenchmarks()

@@ -27,2 +27,4 @@ 'use strict'

this.wildcardChild = null
this.parametricChild = null
this.wildcardBrother = null
this.parametricBrother = null

@@ -38,6 +40,2 @@ this.constrainer = options.constrainer

Node.prototype.getLabel = function () {
return this.prefix[0]
}
Node.prototype.addChild = function (node) {

@@ -47,3 +45,3 @@ var label = ''

case this.types.STATIC:
label = node.getLabel()
label = node.prefix[0]
break

@@ -53,2 +51,3 @@ case this.types.PARAM:

case this.types.MULTI_PARAM:
this.parametricChild = node
label = ':'

@@ -70,7 +69,6 @@ break

this.children[label] = node
this.numberOfChildren++
const nodeChildren = Object.values(this.children)
this.numberOfChildren = nodeChildren.length
this._saveParametricBrother()
this._saveWildcardBrother()

@@ -82,7 +80,5 @@ return this

let parametricBrother = this.parametricBrother
for (const child of Object.values(this.children)) {
if (child.prefix === ':') {
parametricBrother = child
break
}
if (this.parametricChild !== null) {
this.parametricChild.parametricBrother = parametricBrother
parametricBrother = this.parametricChild
}

@@ -93,3 +89,3 @@

for (const child of Object.values(this.children)) {
if (child && child.kind === this.types.STATIC) {
if (child && child !== parametricBrother) {
child.parametricBrother = parametricBrother

@@ -102,2 +98,20 @@ child._saveParametricBrother(parametricBrother)

Node.prototype._saveWildcardBrother = function () {
let wildcardBrother = this.wildcardBrother
if (this.wildcardChild !== null) {
this.wildcardChild.wildcardBrother = wildcardBrother
wildcardBrother = this.wildcardChild
}
// Save the wildcard brother inside static children
if (wildcardBrother) {
for (const child of Object.values(this.children)) {
if (child && child !== wildcardBrother) {
child.wildcardBrother = wildcardBrother
child._saveWildcardBrother(wildcardBrother)
}
}
}
}
Node.prototype.reset = function (prefix) {

@@ -112,2 +126,3 @@ this.prefix = prefix

this.wildcardChild = null
this.parametricChild = null
this.hasConstraints = false

@@ -137,2 +152,6 @@ this._decompileGetHandlerMatchingConstraints()

if (this.parametricChild !== null) {
newChild.parametricChild = this.parametricChild
}
this.reset(this.prefix.slice(0, length))

@@ -147,20 +166,12 @@ this.addChild(newChild)

Node.prototype.findMatchingChild = function (derivedConstraints, path) {
var child = this.children[path[0]]
if (child !== undefined && (child.numberOfChildren > 0 || child.getMatchingHandler(derivedConstraints) !== null)) {
if (path.slice(0, child.prefix.length) === child.prefix) {
return child
Node.prototype.findStaticMatchingChild = function (path, pathIndex) {
const child = this.children[path[pathIndex]]
if (child !== undefined) {
for (let i = 0; i < child.prefix.length; i++) {
if (path.charCodeAt(pathIndex + i) !== child.prefix.charCodeAt(i)) {
return null
}
}
}
child = this.children[':']
if (child !== undefined && (child.numberOfChildren > 0 || child.getMatchingHandler(derivedConstraints) !== null)) {
return child
}
child = this.children['*']
if (child !== undefined && (child.numberOfChildren > 0 || child.getMatchingHandler(derivedConstraints) !== null)) {
return child
}
return null

@@ -212,13 +223,17 @@ }

Node.prototype.getMatchingHandler = function (derivedConstraints) {
if (derivedConstraints === undefined) {
return this.unconstrainedHandler
}
if (this.hasConstraints) {
// This node is constrained, use the performant precompiled constraint matcher
return this._getHandlerMatchingConstraints(derivedConstraints)
} else {
// This node doesn't have any handlers that are constrained, so it's handlers probably match. Some requests have constraint values that *must* match however, like version, so check for those before returning it.
if (derivedConstraints && derivedConstraints.__hasMustMatchValues) {
return null
} else {
return this.unconstrainedHandler
}
}
// This node doesn't have any handlers that are constrained, so it's handlers probably match. Some requests have constraint values that *must* match however, like version, so check for those before returning it.
if (!derivedConstraints.__hasMustMatchValues) {
return this.unconstrainedHandler
}
return null
}

@@ -225,0 +240,0 @@

@@ -401,3 +401,3 @@ 'use strict'

Router.prototype.find = function find (method, path, derivedConstraints) {
var currentNode = this.trees[method]
let currentNode = this.trees[method]
if (currentNode === undefined) return null

@@ -417,5 +417,2 @@

var originalPath = path
var originalPathLength = path.length
if (this.caseSensitive === false) {

@@ -425,24 +422,22 @@ path = path.toLowerCase()

var maxParamLength = this.maxParamLength
var wildcardNode = null
var pathLenWildcard = 0
var decoded = null
var pindex = 0
var params = null
var i = 0
var idxInOriginalPath = 0
const maxParamLength = this.maxParamLength
let pathIndex = currentNode.prefix.length
const params = []
const pathLen = path.length
const parametricBrothersStack = []
const wildcardBrothersStack = []
while (true) {
var pathLen = path.length
var prefix = currentNode.prefix
// found the route
if (pathIndex === pathLen) {
const handle = currentNode.getMatchingHandler(derivedConstraints)
// found the route
if (pathLen === 0 || path === prefix) {
var handle = derivedConstraints !== undefined ? currentNode.getMatchingHandler(derivedConstraints) : currentNode.unconstrainedHandler
if (handle !== null && handle !== undefined) {
var paramsObj = {}
const paramsObj = {}
if (handle.paramsLength > 0) {
var paramNames = handle.params
const paramNames = handle.params
for (i = 0; i < handle.paramsLength; i++) {
for (let i = 0; i < handle.paramsLength; i++) {
paramsObj[paramNames[i]] = params[i]

@@ -460,77 +455,61 @@ }

var prefixLen = prefix.length
var len = 0
var previousPath = path
let node = currentNode.findStaticMatchingChild(path, pathIndex)
// search for the longest common prefix
i = pathLen < prefixLen ? pathLen : prefixLen
while (len < i && path.charCodeAt(len) === prefix.charCodeAt(len)) len++
if (currentNode.parametricChild !== null) {
if (node === null) {
node = currentNode.parametricChild
} else {
parametricBrothersStack.push({
brotherPathIndex: pathIndex,
paramsCount: params.length
})
}
}
if (len === prefixLen) {
path = path.slice(len)
pathLen = path.length
idxInOriginalPath += len
if (currentNode.wildcardChild !== null) {
if (node === null) {
node = currentNode.wildcardChild
} else {
wildcardBrothersStack.push({
brotherPathIndex: pathIndex,
paramsCount: params.length
})
}
}
var node = currentNode.findMatchingChild(derivedConstraints, path)
if (node === null) {
let brotherNodeState
node = currentNode.parametricBrother
if (node === null) {
return this._getWildcardNode(wildcardNode, originalPath, pathLenWildcard, derivedConstraints, params)
node = currentNode.wildcardBrother
if (node === null) {
return null
}
brotherNodeState = wildcardBrothersStack.pop()
} else {
brotherNodeState = parametricBrothersStack.pop()
}
var goBack = previousPath.charCodeAt(0) === 47 ? previousPath : '/' + previousPath
if (originalPath.indexOf(goBack) === -1) {
// we need to know the outstanding path so far from the originalPath since the last encountered "/" and assign it to previousPath.
// e.g originalPath: /aa/bbb/cc, path: bb/cc
// outstanding path: /bbb/cc
var pathDiff = originalPath.slice(0, originalPathLength - pathLen)
previousPath = pathDiff.slice(pathDiff.lastIndexOf('/') + 1, pathDiff.length) + path
}
idxInOriginalPath = idxInOriginalPath -
(previousPath.length - path.length)
path = previousPath
pathLen = previousPath.length
len = prefixLen
pathIndex = brotherNodeState.brotherPathIndex
params.splice(brotherNodeState.paramsCount)
}
var kind = node.kind
currentNode = node
const kind = node.kind
// static route
if (kind === NODE_TYPES.STATIC) {
// if exist, save the wildcard child
if (currentNode.wildcardChild !== null) {
wildcardNode = currentNode.wildcardChild
pathLenWildcard = pathLen
}
currentNode = node
pathIndex += node.prefix.length
continue
}
if (len !== prefixLen) {
return this._getWildcardNode(wildcardNode, originalPath, pathLenWildcard, derivedConstraints, params)
}
let paramEndIndex = pathIndex
// if exist, save the wildcard child
if (currentNode.wildcardChild !== null) {
wildcardNode = currentNode.wildcardChild
pathLenWildcard = pathLen
}
// parametric route
if (kind === NODE_TYPES.PARAM) {
currentNode = node
i = path.indexOf('/')
if (i === -1) i = pathLen
if (i > maxParamLength) return null
decoded = sanitizedUrl.sliceParameter(idxInOriginalPath, idxInOriginalPath + i)
if (decoded === null) {
return this._onBadUrl(originalPath.slice(idxInOriginalPath, idxInOriginalPath + i))
for (; paramEndIndex < pathLen; paramEndIndex++) {
if (path.charCodeAt(paramEndIndex) === 47) {
break
}
}
params || (params = [])
params[pindex++] = decoded
path = path.slice(i)
idxInOriginalPath += i
continue
}

@@ -540,11 +519,3 @@

if (kind === NODE_TYPES.MATCH_ALL) {
decoded = sanitizedUrl.sliceParameter(idxInOriginalPath)
if (decoded === null) {
return this._onBadUrl(originalPath.slice(idxInOriginalPath))
}
params || (params = [])
params[pindex] = decoded
currentNode = node
path = ''
continue
paramEndIndex = pathLen
}

@@ -554,16 +525,10 @@

if (kind === NODE_TYPES.REGEX) {
currentNode = node
i = path.indexOf('/')
if (i === -1) i = pathLen
if (i > maxParamLength) return null
decoded = sanitizedUrl.sliceParameter(idxInOriginalPath, idxInOriginalPath + i)
if (decoded === null) {
return this._onBadUrl(originalPath.slice(idxInOriginalPath, idxInOriginalPath + i))
for (; paramEndIndex < pathLen; paramEndIndex++) {
if (path.charCodeAt(paramEndIndex) === 47) {
break
}
}
if (!node.regex.test(decoded)) return null
params || (params = [])
params[pindex++] = decoded
path = path.slice(i)
idxInOriginalPath += i
continue
if (!node.regex.test(path.slice(pathIndex, paramEndIndex))) {
return null
}
}

@@ -573,56 +538,28 @@

if (kind === NODE_TYPES.MULTI_PARAM) {
currentNode = node
i = 0
if (node.regex !== null) {
var matchedParameter = path.match(node.regex)
const matchedParameter = node.regex.exec(path.slice(pathIndex))
if (matchedParameter === null) return null
i = matchedParameter[1].length
paramEndIndex = pathIndex + matchedParameter[1].length
} else {
while (i < pathLen && path.charCodeAt(i) !== 47 && path.charCodeAt(i) !== 45 && path.charCodeAt(i) !== 46) i++
if (i > maxParamLength) return null
for (; paramEndIndex < pathLen; paramEndIndex++) {
const charCode = path.charCodeAt(paramEndIndex)
if (charCode === 47 || charCode === 45 || charCode === 46) {
break
}
}
}
decoded = sanitizedUrl.sliceParameter(idxInOriginalPath, idxInOriginalPath + i)
if (decoded === null) {
return this._onBadUrl(originalPath.slice(idxInOriginalPath, idxInOriginalPath + i))
}
params || (params = [])
params[pindex++] = decoded
path = path.slice(i)
idxInOriginalPath += i
continue
}
wildcardNode = null
}
}
if (paramEndIndex > pathIndex + maxParamLength) {
return null
}
Router.prototype._getWildcardNode = function (node, sanitizedUrl, len, derivedConstraints, params) {
if (node === null) return null
var decoded = sanitizedUrl.slice(-len)
if (decoded === null) {
return this._onBadUrl(sanitizedUrl.slice(-len))
}
var handle = derivedConstraints !== undefined ? node.getMatchingHandler(derivedConstraints) : node.unconstrainedHandler
if (handle !== null && handle !== undefined) {
var paramsObj = {}
if (handle.paramsLength > 0 && params !== null) {
var paramNames = handle.params
for (i = 0; i < handle.paramsLength; i++) {
paramsObj[paramNames[i]] = params[i]
}
const decoded = sanitizedUrl.sliceParameter(pathIndex, paramEndIndex)
if (decoded === null) {
return this._onBadUrl(path.slice(pathIndex, paramEndIndex))
}
// we must override params[*] to decoded
paramsObj['*'] = decoded
return {
handler: handle.handler,
params: paramsObj,
store: handle.store
}
params.push(decoded)
pathIndex = paramEndIndex
}
return null
}

@@ -629,0 +566,0 @@

{
"name": "find-my-way",
"version": "5.1.1",
"version": "5.2.0",
"description": "Crazy fast http radix based router",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -578,1 +578,27 @@ 'use strict'

})
test('Wildcard node with constraints', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.fail('we should not be here, the url is: ' + req.url)
}
})
findMyWay.on('GET', '*', { constraints: { host: 'fastify.io' } }, (req, res, params) => {
t.equal(params['*'], '/foo1/foo3')
})
findMyWay.on('GET', '/foo1/*', { constraints: { host: 'something-else.io' } }, (req, res, params) => {
t.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.on('GET', '/foo1/foo2', (req, res, params) => {
t.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.lookup(
{ method: 'GET', url: '/foo1/foo3', headers: { host: 'fastify.io' } },
null
)
})
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc